This question already has answers here:
How does one reduce a list of boolean values in Common Lisp?
(3 answers)
Closed 8 years ago.
I'm new to Common Lisp, so this got me a bit stumped and Google has failed me.
I have a function sizzle defined like
(defun sizzle (f &rest r) ...blah blah...)
And now I just need to check if all optional arguments are non-nil, so naturally I did
(apply #'and r)
...and then it turns out that and isn't a function, it's a macro (which I haven't got around to just yet).
So, my question is, is there a way to use macros as functions (much like above), or should I just make my own function to check if all values is a given list are non-nil? Or is there yet another approach I haven't thought of?
You can't use macros as functions (that's why it's better to make some things functions, and that's why compiler macros instead of regular macros are used for optimization).
I would use (every #'identity r) or (notany #'null r) instead of writing my own AND function for your example.
Related
When developing with Common Lisp, we have three possibilities to define new setf-forms:
We can define a function whose name is a list of two symbols, the first one being setf, e.g. (defun (setf some-observable) (…)).
We can use the short form of defsetf.
We can use the long form of defsetf.
We can use define-setf-expander.
I am not sure what is the right or intended use-case for each of these possibilities.
A response to this question could hint at the most generic solution and outline contexts where other solutions are superior.
define-setf-expander is the most general of these. All of setf's functionality is encompassed by it.
Defining a setf function works fine for most accessors. It is also valid to use a generic function, so polymorphism is insufficient to require using something else. Controlling evaluation either for correctness or performance is the main reason to not use a setf function.
For correctness, many forms of destructuring are not possible to do with a setf function (e.g. (setf (values ...) ...)). Similarly I've seen an example that makes functional data structures behave locally like a mutable one by changing (setf (dict-get key some-dict) 2) to assign a new dictionary to some-dict.
For performance, consider the silly case of (incf (nth 10000 list)) which if the nth writer were implemented as a function would require traversing 10k list nodes twice, but in a setf expander can be done with a single traversal.
This question already has answers here:
What does an underscore and interface name after keyword var mean?
(2 answers)
Closed 4 years ago.
while going through this tutorial on writing FUSE filesystems in go, I came across this cryptic assignment:
var _ fs.Node = (*Dir)(nil)
Can someone explain the mechanics of this syntax, and how does it fit in the context in which it is declared? As I understand the outcome of the assignment is actually ignored (and what does the right hand expression even result in? a nil Dir pointer?)
This makes the compiler check if type *Dir fulfills fs.Node interface.
Take a nil pointer, make it a *Dir pointer and assign it to an unnamed variable of interface type fs.Node. Since we never use this variable, we have to make it unnamed.
This question already has an answer here:
`where` in function definitions in julia-0.6
(1 answer)
Closed 5 years ago.
Reading the Julia documentation on parametric methods, I can't for the life of me figure out the difference between these two definitions
julia> function f{T<:Real}(x::T)
println("$x with type $T")
end
julia> function g(x::T) where {T<:Real}
println("$x with type $T")
end
Any guidance on the semantic difference between these two definitions would be highly appreciated.
The former is deprecated (in most instances) for the latter. where replaces the old syntax in v0.7 and onwards, and the first will not exist in 1.0.
One exception is inner constructors. The first syntax will still exist for them. But in that case type parameters means something very different. Example: Array{Float64,2}() the inner constructor takes in the parameters from the user. This was confusing before because type parameters had a dual meaning for these different constructs, but now this way of parameterizing only exists for inner constructors and only means this, whereas everything else uses where.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 5 years ago.
Improve this question
Common Lisp provides many flexible coding options for achieving a given result. However, it is sometimes difficult to choose the best approach. For example, the following vector expressions all produce the same result in different ways.
(defparameter objects (list 1 2 3))
(apply #'vector objects)
(coerce objects 'vector)
(make-array (length objects) :initial-contents objects)
(read-from-string (format nil "#~S" objects))
Of course, some expressions are more flexible than others, depending on the required output; but for a given output as above, what criteria are useful for deciding which to use?
(apply #'vector objects) is subject to the usual limitations of APPLY, which is that objects shouldn't hold more than CALL-ARGUMENTS-LIMIT elements. This is bad style even when you have only a few arguments.
COERCE is great: not only it performs the job, it also conveys the intent very well. However, you won't be able to give additional parameters for the resulting vector (e.g. fill-pointer, etc.); you cannot convert nested lists into matrices.
MAKE-ARRAY gives you full control over the resulting array: adjustability, fill-pointer, dimensions, element-type, displacement.
READ-FROM-STRING is a big no for data conversion, in general. In terms of useless computations, this approach is the Rube Goldberg's version of coerce. It also comes with a lot of security concerns, unless you are 100% sure about what the string contains. Here, you create the string yourself, but if your data contains any value for which another part of the code redefined PRINT-OBJECT, the code might break.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I've been reading sicp trying to understand scheme, specially macros. I noticed that sicp doesnt talk about macros at all. I read on Paul Graham's site that:
The source code of the Viaweb editor was probably about 20-25% macros. Macros are harder to write than ordinary Lisp functions, and it's considered to be bad style to use them when they're not necessary. So every macro in that code is there because it has to be.
So I desperately wanted to know how to write macros and what to use them for, so I read this site about macros: http://www.willdonnelly.net/blog/scheme-syntax-rules/
But that site just explains how to write a "for" macro. I think Paul Graham talks about CL and the other blog talks about scheme, but they are partly the same. So, wat can be an example of something that cannot be done with ordinary procedures and thus must be done with macros?
EDIT: I have already seen a similar question, but wanted to ask if there was some sort of crazy algorithm that you could do with macros that couldn't possible be done with procedures(other than syntactic sugar as described in that question's answer).
Macros are a tricky subject that I've personally reversed my own opinions on no less than a dozen times, so take everything with a grain of salt.
If you are just getting acquainted with macros, you'll find the most helpful to be those macros that clarify or expedite existing expressions.
One such macro that you may have been exposed to is the anaphoric macro, which remains as popular today as the day Paul Graham coined the term:
(define-syntax (aif x)
(syntax-case x ()
[(src-aif test then else)
(syntax-case (datum->syntax-object (syntax src-aif) '_) ()
[_ (syntax (let ([_ test]) (if (and _ (not (null? _))) then else)))])]))
These macros introduce "anaphora" variables, namely it that you can use in the consequent and alternative clauses of an if statement, e.g:
(aif (+ 2 7)
(format nil "~A does not equal NIL." it)
(format nil "~A does equal NIL." it))
This saves you the hassle of typing a let statement -- which can add up in large projects.
More broadly, transformations that change the structure of a program, dynamically generate "templated" code or otherwise "break" rules (that you hopefully know well enough to break!) are the traditional domain of the macro. I could write on and on about how I've simplified countless projects and assignments with macros -- but I think you'll get the idea.
Learning Scheme-style macros is a little daunting, but I assure you that there are excellent guides to syntax-rules-style macros for the merely eccentric, and as you gain more and more experience with macros, you'll probably come to the conclusion that they are a beautiful idea, worthy of the name "Scheme".
If you happen to use Racket (previously known as PLT Scheme) -- It has excellent documentation on macros, even providing a few neat tricks along the way (I'd also guess most of what is written there can be readily written in another Scheme dialect without issue)
Here is one standard answer (part of which is also covered in SICP - see Exercise 1.6 for example; also search for the keyword "special form" in the text): in a call-by-value language like Scheme, an ordinary procedure (function) must evaluate its argument(s) before the body. Thus, special forms such as if, and, or, for, while, etc. cannot be implemented by ordinary procedures (at least without using thunks like (lambda () body), which are introduced for delaying the evaluation of the body and may incur performance overheads); on the other hand, many of them can be implemented with macros as indeed done in RnRS (see, for instance, the definition of and by define-syntax on page 69).
The simple answer is that you can make new syntax where delaying evaluation is essential for the functionality. Imagine you want a new if that works the same way as if-elseif. In Lisp it would be something that is like cond, but without explicit begin. Example usage is:
(if* (<= 0 x 9) (list x)
(< x 100) (list (quotient x 10) (remainder x 10))
(error "Needs to be below 100"))
It's impossible to implement this as a procedure. We can implement something that works the same by demanding the user to give us thunks and thus the parts will become procedures that can be run instead:
(pif* (lambda () (<= 0 x 9)) (lambda () (list x))
(lambda () (< x 100)) (lambda () (list (quotient x 10) (remainder x 10)))
(lambda () (error "Needs to be below 100")))
Now it's easy implementation:
(define (pif* p c a . rest)
(if (p)
(c)
(if (null? rest)
(a)
(apply pif* a rest))))
This is how JavaScript and almost every other language that doesn't support macros do it. Now if you want to give the user the power of making the first instead of the second you need macros. Your macro can write the first to the second so that your implementation can be a function or you can just change the code to a nested if:
(define-macro if*
(syntax-rules ()
((_ x) (error "wrong use of if*"))
((_ p c a) (if p c a))
((_ p c next ...) (if p c (if* next ...)))))
Or if you want to use the procedure it's even simpler to just wrap each argument in a lambda:
(define-syntax if*
(syntax-rules ()
((_ arg ...) (pif* (lambda () arg) ...)))
The need of macros is to reduce boilerplate and simplify syntax. When you see the same structure you should try to abstract it into a procedure. If that is impossible since the arguments are used in special forms you do it with a macro.
Babel, a ES6 to ES5 transpiler converts JavaSript ES6 syntax to ES5 code. If ES5 had macros it would have been as easy as making compability macros to support ES6. In fact most features of newer versions of the language would have been unnecessary since programmers don't have to wait for a new version of a language to give it new fancy features. Almost nothing of new language features in Algol languages (PHP, Java, JavaScript, Python) would have been necessary if the language had hygenic macro support.