I'm trying to implement this logic in Clojure (just an example):
a = 1 + 5
b = a + 3
c = a + 4
d = c + a
return f(a, b, c, d)
The best code I've managed to write so far looks like:
(let [a (+ 1 5) b (+ a 3) c (+ a 4) d (+ c a)] (f a b c d))
This looks rather cumbersome, mostly because in my real-life case these "add" operations are much more complicated and may take a few lines of code. I would rather prefer to write it like (Lisp style):
(set a (+ 1 5))
(set b (+ a 3))
(set c (+ a 4))
(set d (+ c a))
(f a b c d)
Is it possible in Clojure?
No and that is by intent, as the (set ...) calls you're describing imply the use of mutable state in the way languages like Java and C# do. This is something Clojure actively avoids in order to manage state in a more sane way, something that really becomes important in concurrency. For more information I refer you to the Clojure website.
Furthermore, the let form is not cumbersome, it is a useful scoping tool:
In your example a, b,c and d are all local to let. What this means is that once the instruction pointer steps out of the let, all of those bindings are forgotten.
In contrast, even if your (set...) example were to work, you would have polluted your namespace with all of these ephemeral names.
Actually, you almost found the best solution possible in Clojure:
(let [a (+ 1 5)
b (+ a 3)
c (+ a 4)
d (+ c a)]
(f a b c d))
You can't write Clojure code in imperative style, because it's a functional language. You can't freely use defs either, because all variables in Clojure are immutable. So, ones defined the can't be changed. So, if you want to temporary bind some variables, you should use let.
The set function in Clojure creates a set data type from another collection container as opposed to mutating the values of the variables. However, you could do the following:
(def a (+ 1 5))
(def b (+ a 3))
(def c (+ a 4))
(def d (+ c a))
(f a b c d)
The let statement allows you to do the same thing but not "pollute" your top-level namespace with the a, b , c, and d values. However, if you want to be able to hang on to and reference a, b, c, and d, a def would do the trick.
Related
Is it possible to write a define-values macros in Clojure?
Racket language provides such a thing like define-values form which acts in this way
(define -values '(a b c) (1 2 3))
Where a, b, c are global variables now.
How can I do it in Clojure?
(defmacro defvar [x y]
`(let [a# ~x
b# ~y]
(def b# a#)))
(println (defvar 'a 2))
=> #'user/b__2__auto__
;;;It binds the value to auto generated symbol
define-values doesn't make any sense in Clojure. It makes sense in Racket because values lets one expression evaluate to multiple values. In Clojure, an expression always evaluates to exactly one value: there's no values to extract into definitions.
Of course, you can write a macro def-several-things such that
(def-several-things [x y] [1 2])
expands to
(do (def x 1)
(def y 2))
but this is less readable, not more, so nobody does it.
Given:
(defn some-fn
[]
(let [a 1
b 2
c (+ a b)]
(println c)))
and given that there are multiple such functions, where:
a and b have different values;
c is always equal to (+ a b)
is there a way to extract c without making it a function, which accepts a and b as arguments. So, I don't want:
(defn c-outside
[a b]
(+ a b))
(defn some-fn
[]
(let [a 1
b 2
c (c-outside a b)]
(println c)))
but ideally, something like:
(defn c-outside
[]
(+ a b))
(defn some-fn
[]
(let [a 1
b 2
c (c-outside)]
(println c)))
Is there a way to make c-outside look for the values of a and b in the context, in which it is called? Do I need a macro for that?
there is a way to do it using dynamic bindings:
user> (def ^:dynamic a 10)
#'user/a
user> (def ^:dynamic b 20)
#'user/b
user> (defn c-outside []
(+ a b))
user> (defn some-fn []
(binding [a 1
b 2]
(c-outside)))
#'user/some-fn
user> (some-fn)
;;=> 3
user> (c-outside)
;;=> 30
the trick is that you can temporarily rebind some dynamic vars for the 'duration' of some scope.
This is mostly used in clojure for concurrent programming: the dynamically bound vars keep their values in the threads, spawned from inside the block (as far as i remember)
Otherwise, i see more potential harm from this feature, than the profit, since it obscures the code, adding some unneeded implicit behaviour.
Also as far as i know, this is one of the most arguable features in lisps (in common lisp, to be more specific)
Almost in any case it is better to pass a and b values explicitly to the summing function, since it makes in clean and therefore testable, and helps to reason about it's correctness and performance, and increases readability
you could also think of using macro for that, like this for example:
user> (defmacro c-outside-1 []
`(+ ~'x ~'y))
#'user/c-outside-1
user> (defn some-fn-1 []
(let [x 1
y 2]
(c-outside-1)))
#'user/some-fn-1
user> (some-fn-1)
;;=> 3
but that idea is obviously even worse.
I can seem to wrap my head around macros in Clojure. I'm probably missing something basic. First, allow me to describe an example of what I want.
(defmacro macrotest [v] `(d ...))
(def a '(b c))
(macroexpand-1 '(macrotest a))
; => (d (b c))
In other words, the var passed to macrotest is resolved, but not evaluated further.
Providing the macro with the value of the var works:
(defmacro macrotest [v] `(d ~v))
(macroexpand-1 '(macrotest (b c)))
; => (d (b c))
But providing the var does not:
(def a '(b c))
(macroexpand-1 '(macrotest a))
; => (d a)
Is it possible to resolve a var in Clojure macro, but not evaluate its value?
EDIT: What I want seems to be possible with eval:
(defmacro macrotest [v] `(d ~(eval v)))
(def a '(b c))
(macroexpand-1 '(macrotest a))
; => (user/d (b c))
Its important to understand that macros evaluate at compile time, not at runtime.
at compile time var a does not yet have a value, so its value is not passed to the macro, only its name. However, when you explicitly pass the "value" - well, then it exists at compile time, and you see that it "works".
Lexical environment
Using eval inside a macro is bad practice. Sure, the following works:
(macroexpand-1 '(macrotest a))
; => (user/d (b c))
... but then, this does not work as expected:
(macroexpand-1 '(let [a "oh no"]
(macrotest a)))
; => (user/d (b c))
Surely you would like the macro to evaluate a as it was defined locally, not using the global variable bound to it, but you cannot because the macro does not evaluate v in the right lexical context. And this is the key to understanding macros: they take code and produce code; any data manipulated by that code is not available to you yet. In other words, the moment at which macros are expanded might be totally unrelated to the time their resulting code is evaluated: anything you evaluate while a macro is being executed is probably evaluated too soon w.r.t. the relevance of your data.
What do you want to do?
There is a form named macrotest which should accepts an argument, v and then perform as-if you had form d applied to it. But:
(macrotest (b c)) should not evaluate (b c), just copy it untouched to produce (d (b c)).
(macrotest a) should evaluate a, which results in a quoted form, and place that form in the resulting code, also returning (d (b c)).
You have a problem here, because the meaning changes radically in one or the other case. Either you evaluate an argument, in which case you must quote (b c) and you write:
(defmacro macrotest [v] `(d ~v))
... which requires that d is ready to handle quoted arguments; or you are okay with the argument being not evaluated.
With the same d as above, you can quote the argument explicitly:
(defmacro macrotest [v] `(d '~v))
However, if d itself is a macro that does not evaluate its argument, you have to avoid the quote in front of ~v.
I saw the usage of & in Clojure function signature like this (http://clojure.github.io/core.async/#clojure.core.async/thread):
(thread & body)
And this:
(doseq seq-exprs & body)
Does that means the function/macro can accept a list as variable? I also find * is often used to mean multiple parameters can be accepted, like this:
(do exprs*)
Does anyone have ideas about the difference between & and * in function/macro signature? Is there any documentation to explain this syntax?
It means that there can be multiple parameters after the ampersand, and they will be seen as a seq by the function. Example:
(defn g [a & b]
(println a b))
Then if you call:
(g 1 2 3 4)
it will print out 1 (2 3 4) (a is 1, b is a sequence containing 2, 3 and 4).
In clojure binding forms (let, fn, loop, and their progeny), you can bind the rest of a binding vector to a sequence with a trailing &. For instance,
(let [[a b & xs] (range 5)] xs) ;(2 3 4)
Uses of * and other uses of & are conventions for documenting the structure of argument lists.
Is there a way in lisp-family (EDIT: lisp-1) languages to differentiate symbol evaluation with regard to its position as as function or as an argument (i.e. override eval of this symbol in regard to when it is evaluated)?
As an example (I don't need this functionality, this is an example), I wanted to implement some sort of infix operation on a set of objects, which can be called by an object itself
(my-obj some-operator arg1 ...)
which will actually apply function some-operator to my-obj and arguments.
But when this object is used anywhere else in code as an argument, like:
(some-function my-obj &args...)
it will evaluate to a value of my-obj.
Thank you.
In Racket it is possible to do a couple things in this spirit:
You can define a struct and give it a prop:procedure. When an instance of the struct is supplied in an application, the procedure will be called.
You can override the default #%app with your own function, to redefine application generally, and including things that aren't structs. For example you can do things like emulate Clojure's (key map) syntax, so that ('symbol dict) is actually (hash-ref dict 'symbol).
Being a lisp-1 basically means that you do not evaluate the first slot of a combination any differently than any other slots. To get such behavior for code you write anyway, you need to transform it to code that does what you want under the rules of a lisp-1. Thus you will need to implement a macro that performs this transformation.
For example if you want infix operators you need to write some macro infix and then perhaps you could write:
(infix (+ - * /) (1 + 2 * 5 - 3) / 4)
and have it evaluate to 2.
I have been playing around with the idea of a default procedure in a OO CLOS-like Scheme. eg. that writing
(obj 5 10)
Would validate obj and apply it with arguments if obj is a procedure or method, but if it isn't it would be the same as the default dispatcher eg.
(default-dispatcher obj 5 10)
In such Scheme one could make vector accessors:
(define-method default-dispatcher
"Default dispatcher for vectors"
([obj %vector] [index %number]) -> (vector-ref obj index)
([obj %vector] [index %number] value) -> (vector-set! obj index value)
(args ...) -> (error "No such method"))
; example usage
(define vec (vector 4 5 6 7))
[vec 1] ; => 5
[vec 1 10]
[vec 1] ; => 10
In Racket this is possible by changing the languages #%app syntax.
In the TXR Lisp dialect, the problem is approached from the other end. Starting with Lisp-2 dialect as a basis, can we robe ourselves with some of the expressivity advantages of a Lisp-1 dialect, like eliminating the (function ...), #' and funcall noise from programs that make extensive use of higher order functions?
The design is centered around a special operator called dwim, which stands for either "Do What I Mean" or "Dispatch, in a Way that is Intelligent and Meaningful".
Invocations of the dwim operator are sugared over using square brackets, which are called "DWIM Brackets"
The dwim operator isn't just a macro over Lisp-2; it actually changes the name lookup rules. When we have
(dwim a b c (d e f) g)
Or equivalently:
[a b c (d e f) g]
all of the argument forms which are symbolic (a, b, c and g) are resolved using a special rule which conflates together the function and variable namespaces. This is built into the heart of the language. The operator has direct access to the environment to make this possible.
The special treatment does not recurse into (d e f), which is an ordinary Lisp-2 form. You have to put the DWIM Brackets on that if you want the semantics.
Also, the dwim operator is properly handled by macro expansion. For instance, given:
(symacrolet ((localfun whatever))
(flet ((localfun () ...)))
[a b c localfun] ;; refers to the flet as a function object!
(a b c localfun))) ;; refers to the symbol macro!
The macro expander knows about dwim and its semantics, and so it considers the possibility that localfun refers to the function and variable namespace. The closest lexical binding in either namespace is the flet and so the symbol macro expansion is suppressed (shadowed).
The dwim semantics is implicitly used in the partial evaluating op macro and its "cousins" derived from it.
Range Extraction task from Rosetta Code:
(defun range-extract (numbers)
`#{(mapcar [iff [callf > length (ret 2)]
(ret `#[#1 0]-#[#1 -1]`)
(ret `#{#1 ","}`)]
(mapcar (op mapcar car)
(split [window-map 1 :reflect
(op list #2 (- #2 #1))
(sort (uniq numbers))]
(op where [chain second (op < 1)])))) ","}`)
Y Combinator:
;; The Y combinator:
(defun y (f)
[(op #1 #1)
(op f (op [##1 ##1]))])
;; The Y-combinator-based factorial:
(defun fac (f)
(do if (zerop #1)
1
(* #1 [f (- #1 1)])))
;; Test:
(format t "~s\n" [[y fac] 4])
Moreover, various useful things are function callable in TXR Lisp. For instance, every sequence (list, vector or character string) is regarded as a function which maps numeric indices to elements. Thus we can do:
(mapcar "abc" #(2 1 0)) -> #(#\c #\b #\a)
The accepted answer describes a Racket mechanism for treating structures as functions. TXR has this in the form of lambda methods. This is demonstrated in the "OOP-Based" solution to the Accumulator Factory task in Rosetta:
(defstruct (accum count) nil
(count 0))
(defmeth accum lambda (self : (delta 1))
(inc self.count delta))
We can instantiate a (new (accum 9)) which will produce the values 10, 11, 12, ... when invoked as a function. An optional delta argument can be supplied for an increment other than 1:
(let ((acc (new (accum 0))))
(list [acc 5] [acc 5] [acc])) -> (5 10 11)