I am working with this data structure which I call an "associationList", which has the following format:
<| key1->{value1, value2,...}, key2->{value1,value2,...},...|>
I want to have the function Add[assocList_,key_,value_] add key->{value} to the associationList by reference. I have the following code:
Add[assoc_, key_, elt_] :=
If[Head#assoc[key] === Missing,
AppendTo[assoc, key -> {elt}],
AppendTo[assoc[key], elt]];
SetAttributes[AddToAssocList, HoldFirst];
The Add function works for this example:
y=<||>;
Add[y,1,a];
(* y is <|1->{a}|> *)
Add[y,1,b];
(* y is <|1->{a,b}|> *)
But when I change the example to the following, I get an error:
y={<||>};
Add[y[[1]],1,a];
(* y is <|1->{a}|> *)
Add[y[[1]],1,b];
(* Error - Association - "<|1->{a}|> in the part assignment is not a symbol" *)
Using any type of Hold doesn't seem to help. Any ideas?
The answer is to change assoc[key] in Add to assoc[[ Key[key] ]]. This works because assoc[key] gives an association, while assoc[[ Key[key] ]] gives a reference to the association.
Related
I am trying to write a code that calculate the size of a list.
Here is what I've done:
let rec l = function
| [] -> 0
| t::q -> 1 + l q
print_int(l ([1;2;3;4]))
The problem is that it's saying me :
It is applied to too many arguments; maybe you forgot a `;'.
When I put the double semicolon ;; at the end of the definition of l it works well, yet I've read that ;; is not useful at all if you are not coding in the REPL, so here I don't see why it's giving me this error.
The following
print_int(l [1;2;3;4])
is a toplevel expression. Such expression needs to be preceded by ;;:
;; print_int(l [1;2;3;4])
Another option is to make this toplevel expression a binding with
let () = print_int(l [1;2;3;4])
When parsing the code the parser advances until it hits l q. At this point there could be more arguments that should get applied to the function l. So the parser keeps going and the next thing it finds is the value print_int. Another argument to l. Which gives you your error.
The parser has no way of knowing that you had finished the code for the function l. In the top level the special token ;; is used to tell the parser that the input is finished and it should evaluate the code now. After that it starts paring the remaining input again.
Now why doesn't compiled code also have the ';;' token?
Simply because its not needed. In compiled code the line print_int(l [1;2;3;4]) is not valid input. That would be a statement you want to execute and functional languages have no such thing. Instead print_int(l [1;2;3;4]) is an expression that returns a value, () in this case, and you have to tell the compiler what to do with that value. A let () = tells the compiler to match it against (). And the let ... also tells the compiler that the previous let rec l ... has finished. So no special ;; token is needed.
Or think of it this way: In the top level there is an implicit let _ = if your input doesn't start with let. That way you can just type in some expression and see what it evaluates to without having to type let _ = every time. The ';;' token still means "evaluate now" though and is still needed.
I've been looking at the if-let and when-let macros, Im having trouble determining what exactly it is that they "do". In particular, the documentation sais :
clojure.core/when-let
([bindings & body])
Macro
bindings => binding-form test
When test is true, evaluates body with binding-form bound to the value of test
I thus am somewhat confused about the way macros are documented.
1) What does the "=>" symbol mean ?
2) What does "test" refer to ?
Direct answer to your questions:
=> means "expands to", as in BNF notation. In this case it means that you need two forms: binding-form and the test.
"test" means anything that can be evaluated as bool.
By the way, I think that the docs are unclear or even maybe erroneous here. It is hard (or impossible) to deduce that the two forms constituting the bindings need to be enclosed in a vector. IMHO it should be either when-let ([[bindings] & body]) (the vector shown in the args) or bindings => [binding-form test] (the vector shown in the BNF-like expansion.)
It's often helpful when dealing with a macro to call macroexpand and see what the generated code is.
(macroexpand
'(if-let [x (myfunc)]
(foo x)
(bar))
; expands to
(let* [temp__3695__auto__ (myfunc)]
(if temp__3695__auto__ (clojure.core/let [x temp__3695__auto__]
(foo x))
(bar)))
; the generated symbols are necessary to avoid symbol
; capture but can confuse. The above is equivalent to:
(let* [ t (myfunc)]
(if t
(let [x t]
(foo x))
(bar))
So you can see that if-let is a shorthand for "bind local variable to the result of a function call and if that variable is truthy call the first form, else call the other form. The value returned by your function is only available in the 'truthy' branch."
wrt documentation convention
bindings => binding-form test
=> reads something like 'is equivalent to'
test is some form that returns a value
For most of these functions, clojuredocs is your friend, example usage often clarify things. If the clojuredocs example doesn't cut it for you, you can add your own
Consider the following code:
(if-let [x (a-function)]
(do-something-with x) ;; (a-function) returned a truthy result
(do-something-else) ;; (a-function) returned nil or false
This is like let, in that x will be bound to the return value of (a-function). This function could return nil or false. In that case, the implicit test fails and (do-something-else) will be evaluated. If x is not nil and not false, (do-something-with x) will be evaluated.
A scenario where this could be useful:
(if-let [user (find-logged-in-user)]
(do something with logged in user) ;; a user was found
(redirect to login page) ;; no user was found
I sometimes use something like the following, to conditionally add keys to a map of options:
(apply merge {:username "joe"
:email "joe#example.com"}
(when-let [name (find-full-name)] {:name name})
(when-let [dob (find-date-of-birth)] {:dob dob}))
This results in a map with :username and :email keys, and a :name key if the users' full name was found, plus a :dob key if a date of birth was found.
I hope that makes the use of if-let and when-let clearer.
I'd like to export or replicate a scheme environment in another guile process. The algorithm I'm imagining would do something like this to serialize:
(map (lambda (var val) (display (quasiquote (define ,var ,val))
(newline))
(get-current-environment))
And then I'd read/eval that on the other end.
However, while there are functions that return the current environment, they are in some internal format that I can't just map across. How can I "walk" the environment as the above? Alternatively, how else can I replicate an environment into another process?
you may decompose the so-called "current-environment" like this:
(define (get-current-binding-list)
(let* ((e (current-module)) ;; assume checking current-module
(h (struct-ref e 0)) ;; index 0 is current vars hashtable
)
(hash-map->list cons h) ;; return a vars binding list
))
and you can call (get-current-binding-list) to get variables binding list in current-module.
Please note that each element in this list is a pair of symbol and variable type, say, (symbol-name . variable-type). So you may print it like this:
for a instance ,you got a var binding:
(define abc 5)
then:
(let ((vl (get-current-binding-list)))
(assoc-ref vl 'abc)
)
==> #<variable 9bb5108 value: 5>
This result is a "variable type" of variable "abc". You can get it's value with variable-ref procedure.
So you can trace all the bindings and do something ,in your code ,it's simply print var-name and var-value.
I know my answer is too brief, but I think there's enough information to help you to find more details in the manual.
Hope this will help you.
You can't really serialize Scheme environment. I don't known even it's possible to (portably) serialize continuations. Oh, and don't forget about FFIs. Ports and threads are unserializable too.
Here is a short elisp code which shows that the behaviour of a function depends on the name of its variable. Is this a bug?
A function is declared using a variable x. When that function is called with a variable named anything other than x, it works as expected. But if it is called with a variable named x, it fails!
My system is GNU Emacs 22.2.1 (powerpc-apple-darwin8.11.0, Carbon Version 1.6.0) of 2008-04-05 on g5.tokyo.stp.isas.jaxa.jp
Paste this on an emacs buffer, put the cursor after the last parehthesis and press \C-x\C-e to see that the function make-zero does now work correctly when called the second time.
(progn
(defun make-zero (x)
"Simple function to make a variable zero."
(set x 0))
(setq x 10)
(insert "\n Variable x is now equal to " (number-to-string x))
(setq y 20)
(insert "\n Variable y is now equal to " (number-to-string y))
(insert "\n\n Let us apply make-zero to y")
(make-zero 'y)
(insert "\n Variable y is now equal to " (number-to-string y))
(insert "\n\n Let us apply make-zero to x")
(make-zero 'x)
(insert "\n Variable x is now equal to " (number-to-string x))
(insert "\n\n Why make-zero had no effect on x? Is it because the name of the
variable in the definition of make-zero, namely 'x', is the same as the name of
the variable when make-zero was called? If you change the name of the variable
in the definition of make-zero from x to z, this strange behaviour will
disappear. This seems to be a bug in elisp."))
It's not a bug so much as the nature of Elisp's (and Lisp in general) dynamic binding. ' doesn't pass a reference (that is, it's not like & in C/C++), it passes an unevaluated symbol; what it then evaluates to depends on the scope in which it's evaluated, which means it gets the x that's in scope inside the function.
In Lisp-think, the normal way around this would be to use a macro.
(defmacro make-zero (x) (list 'set x 0))
or
(require 'cl)
(defmacro make-zero (x) `(set ,x 0))
It's not a bug. It'd be worth your while reading the manual entry for Scoping Rules For Variable Bindings.
The function you wrote calls set, which takes a symbol (the value of the first argument) and changes its value to the value of the 2nd argument. The make-zero you wrote binds x locally to its input argument, so when you pass in the symbol x, set changes the first binding for x it finds, which happens to be the local binding.
Here's a different example, let's say you just had the following:
(defun print-something (something)
(set 'something "NEW VALUE")
(insert something))
(print-something "OLD") ; inserts "NEW VALUE"
Looking at that snippet of code, does it make sense that the set line changes the local value of something?
It doesn't matter whether or not there's a global setting for the symbol something.
Another example is the following:
(defvar x "some global value") ;# could have used setq here
(let ((x "local binding"))
(set 'x "new value"))
Which binding would you expect the set line to change? The one created by the let or the global one created by defvar?
The function you wrote is (pretty much) doing exactly the same thing as the let, you're creating a local binding for a variable which is seen before the global one.
If you want to pass around a reference to a variable then the only safe way to do that is via macros, which I recommend, but not until you've grasped the basics of lisp (b/c macros are definitely more complicated). That said, don't let me stop you from diving into macros if that's your passion.
A good introduction to programming Emacs lisp can be found here.
geekosaur's answer does a nice job of showing how you'd achieve what you want.
How do I disable all warnings in sbcl? The extra output is rather annoying.
After much faffing about
and slogging through documentation written by people who are apparently allergic to simple concrete examples
(which seems to be most documentation for most things)
I think all you need to do to disable all warnings
is add this line in your .sbclrc file:
(declaim (sb-ext:muffle-conditions cl:warning))
To disable only style-warnings, it's:
(declaim (sb-ext:muffle-conditions cl:style-warning))
I tried to disable specifically the warning that comes up if you enter eg (setq x 1) at a fresh REPL
; in: SETQ X
; (SETQ X 1)
;
; caught WARNING:
; undefined variable: X
;
; compilation unit finished
; Undefined variable:
; X
; caught 1 WARNING condition
By using this:
(declaim (sb-ext:muffle-conditions sb-kernel:redefinition-warning))
but it didn't work,
(apparently redefinition-warning means something else)
and I can't find what it should be.
I guessed sb-kernel:undefined-warning
but that doesn't exist.
Using a macro
Also,
in regards #Bogatyr's answer
(using a macro to automatically run defvar)
and #spacebat's comment
(that the macro evaluated the value twice)
I have this to say:
As another newb coming across this,
I wanted to make demo showing that the macro evals twice,
and showing a version that evaluates only once.
(
I originally edited it in at the end of the question
but it was rejected because:
"This edit was intended to address the author of the post and makes no sense as an edit. It should have been written as a comment or an answer."
Well, you can't answer an answer,
but comments can't take blocks of code,
so I guess I should put it here instead?
)
original
(defmacro sq (var value)
`(progn
(defvar ,var ,value)
(setq ,var ,value)))
(sq v (princ "hi"))
side-effects: prints hihi
return value: "hi"
rewrite 2 - only evals once, always runs defvar
(defmacro sq2 (var value)
(let
((value-to-set value))
`(progn
(defvar ,var)
(setq ,var ,value-to-set))))
(sq2 v (princ "hi"))
side-effects: prints hi
return value: "hi"
rewrite 3 - same as above, but trickier to read
I used value-to-set for clarity,
but you could just use value again with no problems:
(defmacro sq3 (var value)
(let
((value value))
`(progn
(defvar ,var)
(setq ,var ,value))))
(sq3 v (princ "hi"))
rewrite 4 - only runs defvar if the variable is unbound
Running those macros will always define the variable before setting it,
so if v was already "bound" but not "defined"
(ie you had introduced it with setq)
then won't get any more error messages when you use the variable,
or reset it with setq.
Here's a version of the macro
that only runs defvar if the variable is not already bound:
(defmacro sq4 (var value)
(let
((value-to-set value))
(if (boundp var)
`(setq ,var ,value-to-set)
`(progn
(defvar ,var)
(setq ,var ,value-to-set)))))
(sq4 v (princ "hi"))
So if you use it to set a variable that is bound but not defined
it will keep giving you error messages.
(Which is maybe a good thing?
Like, for the same reason-I-don't-actually-know-why the error message exists in the first place.)
[
Also,
I tested the macro on these:
(sq4 value 1 )
(sq4 value 'value )
(sq4 value 'value-to-set )
(sq4 value 'var )
(sq4 value-to-set 1 )
(sq4 value-to-set 'value )
(sq4 value-to-set 'value-to-set )
(sq4 value-to-set 'var )
(sq4 var 1 )
(sq4 var 'value )
(sq4 var 'value-to-set )
(sq4 var 'var )
(You know, checking I hadn't screwed up and... done something weird.)
The ones where I tried to use var as a variable spewed errors.
At first I thought I had messed something up,
but it's actually just reserved for something special in SBCL(?) itself.
(defvar var) gets:
; debugger invoked on a SYMBOL-PACKAGE-LOCKED-ERROR in thread
; #<THREAD "main thread" RUNNING {AB5D0A1}>:
; Lock on package SB-DEBUG violated when globally declaring VAR SPECIAL while
; in package COMMON-LISP-USER.
; See also:
; The SBCL Manual, Node "Package Locks"
So... when in doubt, avoid using the symbol var, I guess.
]
this is what i use to muffle both compile-time and runtime (load-time) redefinition warnings:
(locally
(declare #+sbcl(sb-ext:muffle-conditions sb-kernel:redefinition-warning))
(handler-bind
(#+sbcl(sb-kernel:redefinition-warning #'muffle-warning))
;; stuff that emits redefinition-warning's
))
following this pattern you can install these handlers on superclasses like cl:style-warning to muffle all style warnings.
You can either use SB-EXT:MUFFLE-CONDITIONS as Pillsy said, the other alternative is to read through the warnings and use them to modify your code to remove the warnings. Especially if they're actually warnings (rather than, say, optimization notes).
I couldn't get SB-EXT:MUFFLE-CONDITIONS to work for the highly annoying undefined variable warning even after much googling. That warning drives me nuts when experimenting at the REPL, so I did what all the books suggest we should do: extend lisp to suit my needs/preferences!
I wrote my own setq that shut up the sbcl warnings, my first macro ever :). I'm sure there are better ways to do it but this works great for me, and it's going right into my ~/.sbclrc!
(defmacro sq (var value)
`(progn
(defvar ,var ,value)
(setq ,var ,value)))
You probably want to look at SB-EXT:MUFFLE-CONDITIONS.
If warnings are all you care about you can set:
(setf sb-ext:*muffled-warnings* 'style-warning)
This will only apply to style warnings and allow other warnings and conditions to print out. Any warning that shares the same parent will be automatically muffled.
For me (and probably others), most of the warnings were actually being piped to stdErr.
So this silenced the annoying output:
sbcl 2>/dev/null/
Alternatively, you can pipe to a file.
sbcl 2>myTempLog.txt
When starting sbcl, the problem is that at least in my configuration, alexandria spews out a tonne of method warnings and redifining warnings because of asdf, alexandria and readline, regardless of the mute solutions.
User theoski's solutions (sbcl 2>/dev/null ...) totally work to get rid of those, but at the expense of warnings that might actually be useful.
Still, I always have a repl open in a terminal as a scratch for quick hacks and experimenting, and it's a LOT nicer not seeing that avalanche when loading it up.