This code reveals that f doesn't yet look up q before it's called.
q <- 2
f <- function(x) q + x
f
I want to tell R which symbols in the body to look up right away (in this case list("q")) and have it modify f accordingly. How can it be done?
In Common Lisp this would look like:
CL-USER> (defparameter q 4)
Q
CL-USER> (let ((bar q))
(defmacro f (x)
`(+ ,bar ,x)))
F
CL-USER> (macroexpand-1 `(f 4))
(+ 4 4)
T
In R this could look like:
> q = 2
> f = eval(bquote(function(x) .(q) + x))
> f
function (x)
2 + x
>
Since R is interpreted, eval is par for the course there. With Common Lisp, if you do not want to use eval, you can go with a compile-time macro that carries along with it a hard-coded value for 'q, so that every time it is used in code at that point on it refers to the value of 'q at creation time of the macro.
Actually you are wrong about what happens when you make an assignment for a token of the value of function. Take a look at this:
> environment(f)$q
[1] 2
Some of the base R function keep values hidden away in the environments of the returned objects. The two that come to mind are ecdf and splinefun.
You could use something like this:
f_generator = function(q){
q
function(x){
q + x
}
}
f2 = f_generator(2)
f3 = f_generator(3)
f2(1)
# 3
f3(1)
# 4
I'd like to run a code like
(->> input
(partition-all 5)
(map a-side-effect)
dorun)
asynchronously dividing input and output(a-side-effect).
Then I've written the code to experiment below.
;; using boot-clj
(set-env! :dependencies '[[org.clojure/core.async "0.2.374"]])
(require '[clojure.core.async :as async :refer [<! <!! >! >!!]])
(let [input (range 18)
c (async/chan 1 (comp (partition-all 5)
(map prn)))]
(async/onto-chan c input false)
(async/close! c))
explanation for this code:
Actually elements in input and its quantity is not defined before running and elements in input is able to be taken by some numbers from 0 to 10.
async/onto-chan is used to put a Seq of elements (a fragment of input) into the channel c and will be called many times thus the 3rd argument is false.
prn is a substitute for a-side-effect.
I expected the code above prints
[0 1 2 3 4]
[5 6 7 8 9]
[10 11 12 13 14]
[15 16 17]
in REPL however it prints no characters.
And then I add a time to wait, like this
(let [c (async/chan 1 (comp (partition-all 5)
(map prn)))]
(async/onto-chan c (range 18) false)
(Thread/sleep 1000) ;wait
(async/close! c))
This code gave my expected output above.
And then I inspect core.async/onto-chan.
And I think what happend:
the channel c was core.async/close!ed in my code.
each item of the argument of core.async/onto-chan was put(core.async/>!) in vain in the go-loop in onto-chan because the channel c was closed.
Are there sure ways to put items before close!ing?
write a synchronous version of onto-chan not using go-loop?
Or is my idea wrong?
Your second example with Thread.sleep only ‘works’ by mistake.
The reason it works is that every transformed result value that comes out of c’s transducer is nil, and since nils are not allowed in channels, an exception is thrown, and no value is put into c: this is what allows the producer onto-chan to continue putting into the channel and not block waiting. If you paste your second example into the REPL you’ll see four stack traces – one for each partition.
The nils are of course due to mapping over prn, which is a side-effecting function that returns nil for all inputs.
If I understand your design correctly, your goal is to do something like this:
(defn go-run! [ch proc]
(async/go-loop []
(when-let [value (<! ch)]
(proc value)
(recur))))
(let [input (range 18)
c (async/chan 1 (partition-all 5))]
(async/onto-chan c input)
(<!! (go-run! c prn)))
You really do need a producer and a consumer, else your program will block. I’ve introduced a go-loop consumer.
Very generally speaking, map and side-effects don’t go together well, so I’ve extracted the side-effecting prn into the consumer.
onto-chan cannot be called ‘many times’ (at least in the code shown) so it doesn’t need the false argument.
taking megakorre's idea:
(let [c (async/chan 1 (comp (partition-all 5)
(map prn)))
put-ch (async/onto-chan c (range 18) false)]
(async/alts!! [put-ch])
(async/close! c))
For example in Scheme (count '(1 2 3)) gives 3 and (length '(1 2 3)) also gives 3.
It depends on what interpreter you're using. In standard Scheme, only length is defined. In other interpreters (say, Racket) count exists but it's different, it receives a list and a predicate and returns the number of elements in the list that meet the condition.
I don't know in which interpreter count is defined as a single-parameter function that returns the length of the list, (In Racket (count '(1 2 3)) causes an error), but it seems to me that count is just an alias for length in your interpreter (in other words: they're the same thing) - to be sure, please check the documentation. If I had to choose one, I'd use length, which is standard and will work everywhere.
length returns the number of elements in a list.
count is not a standard procedure mentioned in any of the official Scheme reports (I searched R5RS, R6RS and R7RS) so it's not a part of Scheme. In many implementations you will get some sort of error saying that count does not exist. This is radically different than the expected result you have in your question but it is the more likely result if you were to test it in 5 Scheme implementations.
There is no reason to use a implementation dependent extension when its result is the same as length.
I have tried (count '(1 2 3)) in stalin (r4rs), scm (r5rs), chicken (r5rs), gambit (r5rs), racket (both r5rs and r6rs), ikarus (r6rs), chibi-scheme (r7rs), gauche/gosh (r7rs). None of them have count.
sylwester#pussycat:/p/n/sylwester$ csi
CHICKEN
(c) 2008-2013, The Chicken Team
(c) 2000-2007, Felix L. Winkelmann
Version 4.8.0.5 (stability/4.8.0) (rev 5bd53ac)
linux-unix-gnu-x86-64 [ 64bit manyargs dload ptables ]
compiled 2013-10-03 on aeryn.xorinia.dim (Darwin)
#;1> (count '(1 2 3))
Error: unbound variable: count
Call history:
<syntax> (count (quote (1 2 3)))
<syntax> (quote (1 2 3))
<syntax> (##core#quote (1 2 3))
<eval> (count (quote (1 2 3))) <--
#;1>
sylwester#pussycat:/p/n/sylwester$ gsi
Gambit v4.6.9
> (count '(1 2 3))
*** ERROR IN ##raise-unbound-global-exception -- Unbound variable: count
1>
>
*** EOF again to exit
sylwester#pussycat:/p/n/sylwester$ ikarus
Ikarus Scheme version 0.0.4-rc1+, 64-bit (revision 1870, build 2012-02-21)
Copyright (c) 2006-2009 Abdulaziz Ghuloum
> (count '(1 2 3))
Unhandled exception
Condition components:
1. &undefined
2. &who: eval
3. &message: "unbound variable"
4. &irritants: (count)
>
sylwester#pussycat:/p/n/sylwester$ plt-r5rs
Welcome to Racket v6.1.1.
R5RS legacy support loaded
> (count '(1 2 3))
count: undefined;
cannot reference undefined identifier
context...:
/usr/share/racket/collects/racket/private/misc.rkt:87:7
/usr/share/racket/pkgs/r5rs-lib/r5rs/run.rkt: [running body]
sylwester#pussycat:/p/n/sylwester$ echo "(import (rnrs))
(display (count '(1 2 3)))" > test.scm
sylwester#pussycat:/p/n/sylwester$ plt-r6rs test.scm
test.scm:2:10: count: unbound identifier in module
in: count
context...:
/usr/share/racket/pkgs/r6rs-lib/r6rs/run.rkt: [running body]
sylwester#pussycat:/p/n/sylwester$ chibi-scheme
> (count '(1 2 3))
ERROR on line 1: undefined variable: count
>
sylwester#pussycat:/p/n/sylwester$
sylwester#pussycat:/p/n/sylwester$ gosh
gosh> (length '(1 2 3))
3
gosh> (count '(1 2 3))
*** ERROR: unbound variable: count
Stack Trace:
_______________________________________
gosh>
sylwester#pussycat:/p/n/sylwester$ scm
SCM version 5e5, Copyright (C) 1990-2006 Free Software Foundation.
SCM comes with ABSOLUTELY NO WARRANTY; for details type `(terms)'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `(terms)' for details.
;loading /usr/share/slib/require
;done loading /usr/share/slib/require.scm
;loading /usr/share/slib/require
;done loading /usr/share/slib/require.scm
;loading /usr/lib/scm/Link
;done loading /usr/lib/scm/Link.scm
;loading /usr/lib/scm/Transcen
;done loading /usr/lib/scm/Transcen.scm
> (count '(1 2 3))
;ERROR: "/usr/lib/scm/Iedline.scm": unbound variable: count
; in expression: (count (quote (1 2 3)))
; in top level environment.
;STACK TRACE
1; (##let ((tail (##lambda (c) (##if (##char? ##c) ##c (##let* (( ...
2; (count (quote (1 2 3)))
>
sylwester#pussycat:/p/n/sylwester$ echo "(display (count '(1 2 3)))" > test.scm
sylwester#pussycat:/p/n/sylwester$ stalin -On test.scm
test.scm:1:10:Unbound variable
In python I can do nested list comprehensions, for instance I can flatten the following array thus:
a = [[1,2,3],[4,5,6]]
[i for arr in a for i in arr]
to get [1,2,3,4,5,6]
If I try this syntax in Julia I get:
julia> a
([1,2,3],[4,5,6],[7,8,9])
julia> [i for arr in a for i in arr]
ERROR: syntax: expected ]
Are nested list comprehensions in Julia possible?
This feature has been added in julia v0.5:
julia> a = ([1,2,3],[4,5,6],[7,8,9])
([1,2,3],[4,5,6],[7,8,9])
julia> [i for arr in a for i in arr]
9-element Array{Int64,1}:
1
2
3
4
5
6
7
8
9
List comprehensions work a bit differently in Julia:
> [(x,y) for x=1:2, y=3:4]
2x2 Array{(Int64,Int64),2}:
(1,3) (1,4)
(2,3) (2,4)
If a=[[1 2],[3 4],[5 6]] was a multidimensional array, vec would flatten it:
> vec(a)
6-element Array{Int64,1}:
1
2
3
4
5
6
Since a contains tuples, this is a bit more complicated in Julia. This works, but likely isn't the best way to handle it:
function flatten(x, y)
state = start(x)
if state==false
push!(y, x)
else
while !done(x, state)
(item, state) = next(x, state)
flatten(item, y)
end
end
y
end
flatten(x)=flatten(x,Array(Any, 0))
Then, we can run:
> flatten([(1,2),(3,4)])
4-element Array{Any,1}:
1
2
3
4
You can get some mileage out of using the splat operator with the array constructor here (transposing to save space)
julia> a = ([1,2,3],[4,5,6],[7,8,9])
([1,2,3],[4,5,6],[7,8,9])
julia> [a...]'
1x9 Array{Int64,2}:
1 2 3 4 5 6 7 8 9
Any reason why you're using a tuple of vectors? It's much simpler with arrays, as Ben has already shown with vec. But you can also use comprehensions pretty simply in either case:
julia> a = ([1,2,3],[4,5,6],[7,8,9]);
julia> [i for i in hcat(a...)]
9-element Array{Any,1}:
1
2
⋮
The expression hcat(a...) "splats" your tuple and concatenates it into an array. But remember that, unlike Python, Julia uses column-major array semantics. You have three column vectors in your tuple; is that what you intend? (If they were row vectors — delimited by spaces — you could just use [a...] to do the concatenation). Arrays are iterated through all elements, regardless of their dimensionality.
Don't have enough reputation for comment so posting a modification #ben-hammer. Thanks for the example of flatten(), it was helpful to me.
But it did break if the tuples/arrays contained strings. Since strings are iterables the function would further break them down to characters. I had to insert condition to check for ASCIIString to fix that. The code is below
function flatten(x, y)
state = start(x)
if state==false
push!(y, x)
else
if typeof(x) <: String
push!(y, x)
else
while (!done(x, state))
(item, state) = next(x, state)
flatten(item, y)
end
end
end
y
end
flatten(x)=flatten(x,Array(Any, 0))
Using Common Lisp I am trying loop through a list of students and if the GPA is greater than or equal to 3.0 I want to push a 1 onto another list called equal_names. The problem I am having is the interpreter keeps saying the GPA in the comparison list is "not of type (or rational float)". Why am I getting this error?
Yes, this is for homework. Also this is my first time asking on here, so if you need anything else please let me know.
Sample of the list I am getting the GPA from, where the GPA is 2.307...:
(SETQ students (LIST
(LIST (LIST 'Abbott 'Ashley 'J) '8697387888 'NONE 2.3073320999676614)))
The code I have written:
(setq gpa_count ())
(loop for x in students
if(>= 3.0 (cdr (cdr (cdr x))))
do(push '1 gpa_count))
Given a non-empty list cdr returns the tail of that list, i.e. the list that contains all the elements of the list but the first. The important thing to note is that it returns a list, not an element. That is (cdr (cdr (cdr x))) returns the list (2.30733...), not the float 2.30733.
The loop iterates the outer list. To understand the code in the loop you can look at the first element in students, which is:
'((Abbott Ashley J) 8697387888 NONE 2.3073320999676614)
Now we are going to orientate the list. Every time you pass an element add a d.
Every time you pick a value or go to a list in the list you add an a.
To find how to access the number 2.307.... You look at the first element element in the list:
(Abbott Ashley J) d
8697387888 d
NONE d
Now we are at the part that you are interested in, ie. (2.3073320999676614)), thus you add an a. Now order those in reverse and put a c in front and a r in the end.. It becomes cadddr In light of that your loop should be:
(setq students '(("Mary Larson" 333 NONE 1.1)
("Mina Morson" 333 NONE 2.5)
("Magnus Outsider" 333 NONE 4.1)))
(setq gpa_count ())
(loop for x in students
if (>= 3.0 (cadddr x))
do (push '1 gpa_count))
gpa_count ; ==> (1 1)
Another example:
(setq x (1 (2 3) (3 4 (5 6) 7))) ; ==> (1 (2 3) (3 4 (5 6) 7))
To get the 3*. We follow the parts. 1 == d, (2 3) == a, 2 ==d, 3* == a. In reverse: adad and add c and r to the ends ==> cadadr. thus:
(cadadr '(1 (2 3) (3 4 (5 6) 7))) ; ==> 3
To get the 5. we do the same 1 == d, (2 3) == d and then we have the list we want ==a.
Then 3 ==d, 4 ==d, (5 6) ==a. The 5 is the first element == a. In reverse aaddadd. Now CL guarantees 4 letters accessors so we need to split it up in 4s from the right. Thus it becomes:
(caadr (cdaddr '(1 (2 3) (3 4 (5 6) 7)))) ; ==> 5
Now, without describing you can pick any number or list. Eg. to get (5 6) ddadda, in reverse and split up becomes (cadr (cdaddr x))
Hope it helps.
If your data format is consistent then
(fourth x)
will return the GPA.
Going further,
(setf (symbol-function 'gpa)(function fourth))
would provide
(gpa x)
as "an accessor" for the gpa in the data structure.
My CLISP 2.49 gives this error message:
*** - >=: (2.307332) is not a real number
Let's look at that error message: >=: (2.307332) is not a real number.
The error happens at the call to >= and one argument is a list of a number, not a number.
Since you try to extract the number from a list, does that extract work?
We see that you call CDR. CDR of a list returns a list. So there is the error. You need to extract the number from the list.
Btw., CLISP has commands like help, where, backtrace, ... to further investigate the problem. Just type help and return, without anything else, and you see a list of commands.