Hiring guide for Lisp Engineers

Lisp Developer Hiring Guide

Lisp, developed by John McCarthy in 1958 at MIT, is one of the oldest high-level programming languages still in widespread use today. It was originally created as a practical mathematical notation for computer programs and quickly became the favored language for artificial intelligence (AI) research. The language's fully parenthesized prefix notation allows it to process symbolic information effectively, making it particularly suitable for AI programming. Lisp has spawned many variant languages such as Scheme and Clojure and has significantly influenced Python, Ruby, and others with its distinctive features like code-as-data philosophy and powerful macro system. Its longevity testifies to its innovative design features that continue to inspire modern software development paradigms. Sources: 1) McCarthy J., "Recursive Functions of Symbolic Expressions," Communications of the ACM 3(4), April 1960. 2) Seibel P., "Coders at Work: Reflections on the Craft of Programming," Apress, Septembe

Ask the right questions secure the right Lisp talent among an increasingly shrinking pool of talent.

First 20 minutes

General Lisp app knowledge and experience

The first 20 minutes of the interview should seek to understand the candidate's general background in Lisp application development, including their experience with various programming languages, databases, and their approach to designing scalable and maintainable systems.

What are the basic data types in Lisp?
The basic data types in Lisp include: integers, floating-point numbers, characters, symbols, cons cells, lists, vectors, hash-tables, and strings.
How would you define a function in Lisp?
In Lisp, a function is defined using the 'defun' keyword. For example, a function to add two numbers would be defined as: (defun add-two-numbers (a b) (+ a b)).
What are the uses of the 'car' and 'cdr' functions in Lisp?
'car' and 'cdr' are used to access the elements of a list. 'car' returns the first element of the list, while 'cdr' returns all elements except the first one.
Describe the difference between 'let' and 'setq' in Lisp.
'let' is used to create local variables while 'setq' is used to set the value of an existing variable. 'let' creates a new lexical environment, whereas 'setq' does not.
How would you implement recursion in Lisp?
Recursion in Lisp can be implemented by calling the function within its own definition. For example, a recursive function to calculate factorial would be: (defun factorial (n) (if (<= n 1) 1 (* n (factorial (- n 1)))).
The hiring guide has been successfully sent to your email address.
Oops! Something went wrong while submitting the form.

What you’re looking for early on

Does the candidate demonstrate a solid understanding of Lisp syntax and semantics?
How well does the candidate understand functional programming concepts?
Can the candidate articulate their problem-solving approach using Lisp?
What is the candidate's experience with Lisp-based projects?

Next 20 minutes

Specific Lisp development questions

The next 20 minutes of the interview should focus on the candidate's expertise with specific backend frameworks, their understanding of RESTful APIs, and their experience in handling data storage and retrieval efficiently.

What is a lambda function in Lisp and how would you define one?
A lambda function in Lisp is an anonymous function. It can be defined using the 'lambda' keyword. For example, a lambda function to add two numbers would be: (lambda (a b) (+ a b)).
What are macros in Lisp and what are they used for?
Macros in Lisp are used to define new syntax or new control structures. They are functions that operate on code to produce new code, which is then compiled and executed.
How would you handle exceptions in Lisp?
Exceptions in Lisp can be handled using the 'condition-case' function. It takes three arguments: a variable to bind the error data, the body of code to execute, and a list of handlers for different types of errors.
Describe the difference between 'load' and 'require' in Lisp.
'load' is used to load a file and execute its contents, regardless of whether it has been loaded before. 'require' is used to load a file only if it hasn't been loaded before.
What is tail recursion in Lisp and why is it important?
Tail recursion in Lisp is a form of recursion where the recursive call is the last operation in the function. It is important because it allows the Lisp interpreter to optimize the recursion, saving stack space.
The hiring guide has been successfully sent to your email address.
Oops! Something went wrong while submitting the form.

The ideal back-end app developer

What you’re looking to see on the Lisp engineer at this point.

At this point, a skilled Lisp engineer should demonstrate strong problem-solving abilities, proficiency in Lisp programming language, and knowledge of software development methodologies. Red flags include lack of hands-on experience, inability to articulate complex concepts, or unfamiliarity with standard coding practices.

Digging deeper

Code questions

These will help you see the candidate's real-world development capabilities with Lisp.

What does this simple Lisp code do?
(defun square (n) (* n n))
This code defines a function named 'square' that takes one argument 'n'. It returns the square of 'n' by multiplying 'n' with itself.
What does this Lisp code do?
(defun factorial (n) (if (<= n 1) 1 (* n (factorial (- n 1)))))
This code defines a recursive function named 'factorial' that calculates the factorial of a given number 'n'. If 'n' is less than or equal to 1, it returns 1. Otherwise, it multiplies 'n' with the factorial of 'n-1'.
What will be the output of this Lisp code?
(mapcar #'(lambda (x) (* x x)) '(1 2 3 4 5))
This code applies a lambda function to each element of the list '(1 2 3 4 5)'. The lambda function squares each element. The output will be a new list '(1 4 9 16 25)'.
What does this Lisp code do?
(defun parallel (proc1 proc2) (let ((t1 (make-thread proc1)) (t2 (make-thread proc2))) (thread-join t1) (thread-join t2)))
This code defines a function named 'parallel' that takes two procedures as arguments. It creates two threads 't1' and 't2' for the two procedures and then waits for both threads to finish execution using 'thread-join'.

Wrap-up questions

Final candidate for Lisp Developer role questions

The final few questions should evaluate the candidate's teamwork, communication, and problem-solving skills. Additionally, assess their knowledge of microservices architecture, serverless computing, and how they handle Lisp application deployments. Inquire about their experience in handling system failures and their approach to debugging and troubleshooting.

What are the different types of lists in Lisp?
Lisp has several types of lists, including: proper lists, which are either empty or have a proper list as their tail; dotted lists, which have a non-list value as their tail; and circular lists, which have themselves as their tail.
How would you use higher-order functions in Lisp?
Higher-order functions in Lisp are functions that can take other functions as arguments or return functions as results. For example, the 'mapcar' function applies a given function to each element of a list and returns a list of the results.
What is the Common Lisp Object System (CLOS) and what features does it provide?
CLOS is the object-oriented programming system provided by Common Lisp. It provides features such as multiple inheritance, multi-methods, method combination, and meta-object protocol.

Lisp application related

Product Perfect's Lisp development capabilities

Beyond hiring for your Lisp engineering team, you may be in the market for additional help. Product Perfect provides seasoned expertise in Lisp projects, and can engage in multiple capacities.