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
Related
I'm playing with clojure to do a script to read as input a sequence of URIs from a file and do a report on the status code for them.
I've implemented this using clojure.core.async/pipeline-async to execute the HTTP call to the URI (using an httpkit async call).
I want to monitor the execution of the script so I've an atom for the state:
(let [processing (atom [(System/currentTimeMillis) 0])]
and a function to track the progress.
(defn track-progress [total progress]
(swap! progress
(fn [[time count]]
(let [incremented-count (inc count)
now (System/currentTimeMillis)]
(if (= 0 (mod incremented-count (max 1 (int (/ total 20)))))
(do
(println (str "Progress " incremented-count "/" total " | " (- now time) "ms"))
[now incremented-count])
[time incremented-count])))))
Using it after the HTTP call:
(a/pipeline-async
parallelism
output-chan
(fn [[an-id uri] result]
(http/head uri {:throw-exceptions false
:timeout timeout}
(fn [{:keys [status error]}]
(track-progress total processing)
(a/go
(if (nil? error)
(do (a/>! result [an-id (keyword (str status))])
(a/close! result))
(do (a/>! result [an-id :error])
(a/close! result)))))))
input-chan)
The processing atom is created in a let expression, using that pipeline-async part.
Everything seems working fine, apart from that log.
I found out that sometimes the logging is very weird, having stuffs like this:
Progress 500/10000 | 11519ms
Progress 500/10000 | 11519msProgress 500/10000 | 11519ms
Progress 1000/10000 | 11446ms
Progress 1000/10000 | 11446ms
Progress 1500/10000 | 9503ms
Progress 2000/10000 | 7802ms
Progress 2500/10000 | 12822ms
Progress 2500/10000 | 12822msProgress 2500/10000 | 12822ms
Progress 2500/10000 | 12822ms
Progress 3000/10000 | 10623ms
Progress 3500/10000 | 9018ms
Progress 4000/10000 | 9618ms
Progress 4500/10000 | 13544ms
Progress 5000/10000 | 10541ms
Progress 5500/10000 | 10817ms
Progress 6000/10000 | 8921ms
Progress 6500/10000 | 9078ms
Progress 6500/10000 | 9078ms
Progress 7000/10000 | 9270ms
Progress 7500/10000 | 11826msProgress 7500/10000 | 11826msProgress 7500/10000 | 11826ms
The output is formatted as it is wrote in the shell, it seems that sometimes the same println is executed multiple times, or the fn passed to the swap! function is executed in parallel (no concurrency) in the atom.
(If the the println I remove the str to create the string to print, the lines in which I have the same progress multiple times are totally mixed up like ProgressProgress 7500/10000 | 11826ms7500/100007500 | 11826msProgress/10000 | 11826ms)
Is it something wrong with my code?
Or I am getting the atom wrong, as I supposed it not allows the parallel execution of a function changing its state?
A Clojure atom is designed specifically so that in a multi-threaded program, there can be multiple threads executing swap! on a single atom, and if your program does this, those update functions f given to swap! can run simultaneously. The only part of swap! that is synchronized is a 'compare and swap' operation that effectively does:
lock the atom's state
check if its current value is identical? to the reference it contained before f began executing, and if it is, replace it with the new object returned by f.
Unlock the atom's state".
The function f may take a long time to calculate a new value from the current one, but the critical section above is merely a pointer comparison, and if equal, a pointer assignment.
That is why the doc string for swap! says "Note that f may be called multiple times, and thus should be free of side effects."
What you want is to serialize the output stream from a group of concurrently executing threads. You could use an agent to serialize access to a piece of mutable state, but here you have a degenerate case without state, only with side-effects. For this case, the locking function is all you need.
An example:
(ns tst.demo.core
(:use demo.core tupelo.core tupelo.test))
(defn do-println
[& args]
(apply println args))
(def lock-obj (Object.))
(defn do-println-locking
[& args]
(locking lock-obj
(apply println args)))
(def sleep-millis 500)
(defn wait-and-print
[print-fn id]
(Thread/sleep sleep-millis)
(print-fn (format "wait-and-print %s is complete" id)))
(defn start-threads
[print-fn count]
(println "-----------------------------------------------------------------------------")
(let [futures (forv [i (range count)]
(future (wait-and-print print-fn i)))]
(doseq [future futures]
; block until future is complete
(deref future))))
(dotest
(start-threads do-println 10)
(start-threads do-println-locking 10))
Typical result:
--------------------------------------
Clojure 1.10.2-alpha1 Java 15
--------------------------------------
Testing tst.demo.core
-----------------------------------------------------------------------------
wait-and-print 4 is completewait-and-print 3 is completewait-and-print 2 is complete
wait-and-print 8 is completewait-and-print 9 is complete
wait-and-print 6 is completewait-and-print 1 is complete
wait-and-print 7 is complete
wait-and-print 0 is complete
wait-and-print 5 is complete
-----------------------------------------------------------------------------
wait-and-print 5 is complete
wait-and-print 8 is complete
wait-and-print 7 is complete
wait-and-print 9 is complete
wait-and-print 6 is complete
wait-and-print 3 is complete
wait-and-print 0 is complete
wait-and-print 4 is complete
wait-and-print 2 is complete
wait-and-print 1 is complete
So you can see the output without serialization from locking is jumbled, while each println in the 2nd case is allowed to complete one-at-a-time (even though the order is still random).
If println printed one char at a time instead of one string at a time, the results in the unsynchronized case would be even more jumbled. Modify the output functions to print each character separately:
(defn do-println
[& args]
(doseq [ch (str/join args)]
(print ch))
(newline))
(def lock-obj (Object.))
(defn do-println-locking
[& args]
(locking lock-obj
(apply do-println args)))
with typical result:
--------------------------------------
Clojure 1.10.2-alpha1 Java 15
--------------------------------------
Testing tst.demo.core
-----------------------------------------------------------------------------
wwwwwaaawwiiiattti--taaa--nnaiddnaa--dwpp-irrptaiir-niiantnttn -dw2ta- ani96ipds trn- i-pcndrota-impn nrpd4itl- n eipt5tr s e7i
incisots mc0cpo olmmieppstll ee
etctteo
e-
amnidps-l pectroeai
intt- a1n di-sip rcsio nmctmpo plm3lew etaiei
spt t-lceeatone
d
m-pplreitnet
8 is complete
-----------------------------------------------------------------------------
wait-and-print 3 is complete
wait-and-print 9 is complete
wait-and-print 8 is complete
wait-and-print 4 is complete
wait-and-print 6 is complete
wait-and-print 7 is complete
wait-and-print 0 is complete
wait-and-print 1 is complete
wait-and-print 5 is complete
wait-and-print 2 is complete
but we see that locking serializes the function calls so that the active call must complete before the next can begin.
Some samples I use from Freesound.org have a slight click at the end, e.g.:
repl> (use 'overtone.live)
nil
repl> (def stick (freesound 82280))
#'repl/stick
repl> (stick)
So I'm trying to wrap this sample in an envelope, however all I get is silence. I suspect there's something wrong with my use of buf-rd...
(definst stick1
[amp 0.7]
(let [env (env-gen (perc) :action FREE)
phase (phasor:ar :start 0 :end 1 :rate 1)
index (* phase (buf-frames stick))
snd (buf-rd 1 stick index)]
(* amp env snd)))
(stick1)
play-buf is the correct function to encorporate a sample in an envelope. perc is used to set an attack of 0.01 seconds, and a release of 1 second before silence, thus killing the click.
(def stick (freesound 82280))
(definst stick1
[amp 0.7]
(let [env (env-gen (perc 0.01 1) :action FREE)
snd (play-buf 1 stick)]
(* amp env snd)))
(stick1)
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))
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.
(defmacro nif [expr pos zer neg]
'(condp = (Integer/signum ~expr)
-1 ~neg
0 ~zer
1 ~pos))
I get this error.
1:1 user=> #<Namespace Chapter7Macros>
1:2 Chapter7Macros=> (nif 1 (+ 2 2) (- 2 2) (- 3 2))
1:3 Chapter7Macros=> java.lang.Exception: Unable to resolve symbol: expr in this context (repl-1:57)
Replace the quote (') by a backtick (`) to enable syntax-quoting.
In general using (macroexpand-1 '(nif 1 ... )) will help a lot by showing you the code your macro is actually translating into.