I am looking for something like:
(printem 1 2)
1 2
I assume you do this with a format call, but the examples don't focus on this. Or maybe you write to a string and output that? But that doesn't seem right either.
You can simply build a function that prints all its arguments by the iteration construct of format.
(defun printem (&rest args)
(format t "~{~a~^ ~}" args))
Usage:
CL-USER> (printem 1 2 3)
1 2 3
CL-USER> (printem '(1 2 3) '(4 5 6))
(1 2 3) (4 5 6)
In Common Lisp you can write:
(format t "~d ~d~%" 1 2)
See A Few FORMAT Recipes from Peter Seibel's Practical Common Lisp (other chapters might interest you too).
The function you want could be written like
(defun printem (&rest args)
(dolist (el args)
(princ el)
(princ #\SPACE)))
>> (printem 1 2)
1 2
Related
I have the following (extremely large) lazy-seq:
(def lazy-list (partition-all 100000 (take 10000000000000000000 (repeat 1))))
I want to count the number of elements in it, for which I am doing the following:
(time
(loop [ll lazy-list
c 0]
(if-not (seq (take 1 ll))
c
(recur (drop 1 ll)
(inc c)))))
If I run this I get the following error:
Execution error (OutOfMemoryError) at user/eval2043$fn (REPL:1).
Java heap space
But if I am not holding the head anywhere, why am I seeing this OOM issue?
But if I am not holding the head anywhere ... ? The head of the sequence is held by lazy-list.
I tried a slightly different version and it worked:
(ns tst.demo.core
(:use demo.core tupelo.core tupelo.test))
(dotest
(let [obj (vec (repeat 100000 2)) ]
(loop [ll (repeat 1e8 obj)
cnt 0]
; (spyx (type ll)) ; first is "clojure.lang.Repeat", rest are "clojure.lang.LazySeq"
(if-not (seq (take 1 ll))
(spyx cnt)
(recur (drop 1 ll)
(inc cnt))))
))
with result
-------------------------------
Clojure 1.10.3 Java 17
-------------------------------
Testing tst.demo.core
cnt => 100000000
Ran 2 tests containing 0 assertions.
0 failures, 0 errors.
Passed all tests
Finished at 11:42:52.954 (run time: 10.706s)
Going back to your example, I tried:
(ns tst.demo.core
(:use demo.core tupelo.core tupelo.test))
(def take-item (take 1e7 (repeat 1)))
(def lazy-list (partition-all 1e4 take-item ))
(dotest
(spyx (type take-item))
(spyx (type lazy-list))
(time
(loop [ll lazy-list
c 0]
(if-not (seq (take 1 ll))
(spyx c)
(recur (drop 1 ll)
(inc c)))))
)
with result
-------------------------------
Clojure 1.10.3 Java 17
-------------------------------
Testing tst.demo.core
(type take-item) => clojure.lang.LazySeq
(type lazy-list) => clojure.lang.LazySeq
c => 1000
"Elapsed time: 2787.211076 msecs"
Ran 2 tests containing 0 assertions.
0 failures, 0 errors.
Passed all tests
Finished at 11:50:42.880 (run time: 2.811s)
But note that take-item is holding on to the head of the 10 million long list of ones. I suspect that is your problem.
The moral of the story is that lazy sequences are sometimes useful, but are tricky and easy to get wrong. Then are not a miracle, can often cause unexpected bugs, and I prefer to always use concrete vectors whenever possible.
I'd recommend to only use a lazy sequence if there is no other choice possible.
I wanted to try meta-sexp package. It's a PEG-like parser library. Now, it has a method create-parser-context which can only take string or string-stream. (This is where the parsed content comes from.) However, open and friends create file-stream.
I've looked into flexi-streams library, but couldn't find a straight-forwad way to do it (I could use octets-to-string to create a buffer, feeding it to a bidirectional stream etc... but it's a lot of plumbing). I feel like I'm missing something obvious, and it should be as easy as calling some flexi-stream wrapper function.
I think that you do need to work with the way of transforming streams from the system meta-sexp readme:
meta-sexp uses in-memory string vectors, instead of commonly used
streams, for efficiently stepping backward and forward through the
input.
So meta-sexp works normally with characters and strings, it has implemented some type checkers:
CL-USER> (ql:quickload :meta-sexp)
To load "meta-sexp":
Install 1 Quicklisp release:
meta-sexp
Downloading http://beta.quicklisp.org/archive/meta-sexp/2010-10-06/meta-sexp-0.1.6.tgz
##########################################################################
; Loading "meta-sexp"
[package meta-sexp]......
(:META-SEXP)
CL-USER> (use-package :meta-sexp)
T
CL-USER> (alpha? #\c)
T
CL-USER> (alpha? #\3)
NIL
CL-USER> (digit? #\3)
3 (2 bits, #x3, #o3, #b11)
Then you can use this defining rules to work with strings like the example in the readme:
CL-USER> (defrule integer? (&aux (sign 1) d (num 0)) ()
(:? (:or (:and "-" (:assign sign -1))
"+"))
(:+ (:assign d (:type digit?))
(:assign num (+ (* num 10)
(- (char-code d) #.(char-code #\0)))))
(:return (* sign num)))
CL-USER> (defrule integer? (&aux (sign 1) d (num 0)) ()
(:? (:or (:and "-" (:assign sign -1))
"+"))
(:+ (:assign d (:type digit?))
(:assign num (+ (* num 10)
(- (char-code d) #.(char-code #\0)))))
(:return (* sign num)))
now let's suppose that we have this file
parser-test.txt:
patata
123
calimero
34
32
we can read as follows (read-line returns a string):
CL-USER> (with-open-file (stream "parser-test.txt")
(loop for line = (read-line stream nil)
while line
do (print line)))
"patata"
"123"
"calimero"
"34"
"32"
NIL
then apply the parser:
CL-USER>
; No values
CL-USER> (with-open-file (stream "parser-test.txt")
(loop for line = (read-line stream nil)
while line
do (print (integer? (create-parser-context line)))))
NIL
123
NIL
34
32
NIL
you can read files, by character, by line ..., take a look at hypersec function read; finally I would recommend this nice post with a big lesson of lisp Lisp: It's Not About Macros, It's About Read
I am trying to learn the use of delay and force in Scheme. I created a function which outputs the even numbers in the list. Now I am trying to use delay and force with function. But I am getting error : unbound symbol : "delay" [].
Can someone explain what I am doing wrong?
(define (even-filter ls)
(if (null? ls) '()
(filter even? ls)))
(even-filter '(1 2 3 4 5 88))
(let ((delayed (delay (even-filter '(1 2 3 4 5 88)))))
(force delayed))
Make sure that you're using the right language, because both force and delay are primitive forms, part of the standard language. If using Racket, in the bottom-left corner select "Determine language from source", and type the following:
#lang racket
(define (even-filter ls)
(filter even? ls))
(let ((delayed (delay (even-filter '(1 2 3 4 5 88)))))
(force delayed))
It works as expected:
'(2 4 88)
I'm totally new to Scheme, functional programming, and specifically streams. What are the first five integers in the following stream?
(define (mystery x y z)
(cons x
(lambda ()
(mystery y z (+ x y z)))))
(mystery 1 2 3)
How does this work, and how can I use it in Racket?
We can examine the contents of an infinite stream by implementing a procedure that consumes a given number of elements and returns them in a list, for example:
(define (print strm n)
(if (zero? n)
'()
(cons (car strm)
(print ((cdr strm)) (sub1 n)))))
If we apply it to your stream, here's what we obtain:
(print (mystery 1 2 3) 5)
=> '(1 2 3 6 11)
Although in this case, it'll be more useful if we try to understand what's happening under the hood. In the end, this is just a series of procedure invocations, if we take note of the parameters that get passed at each call it's easy to find the answer. Take a look at the first column in the following table, and remember that the stream is being built by consing all the x's:
x y z
--------
1 2 3
2 3 6
3 6 11
6 11 20
11 20 37
This returns a list consisting of a number and a function. The function is - after the first call - the same as you'd get by calling (mystery 2 3 6)
How does it work? cons just makes a list of its two arguments, which in this case are a value and the result of evaluating a lambda function, which is itself a function
my task is to parse that list
(100 30 5 . 50 6)
to number 135.56
format of input list is always the same
and I've wrote:
(reduce
'string-concat
(mapcar
(lambda (x) (remove #\0 x))
(mapcar
'write-to-string
l
)
)
)
and output I've "135|.|56"
and then read-from-string does'n read it, so...
have You any idea how I can do this parsing?
using or not code above
Your approach does not look particular robust. Also it is kind of difficult to understand what the input list is. Is the dot a symbol, like in |.|? The vertical bars are escaping the name, so that it does not collide with the built-in usage of the dot character in Lisp. It is used in dotted pairs, which stand for cons cells: (a . b).
If it is a symbol, then you can write the symbol without escaping to a string. First, with escaping:
CL-USER 5 > (write-to-string '|.|)
"\\."
Next, without:
CL-USER 6 > (princ-to-string '|.|)
"."
Your list (100 30 5 . 50 6) isn't a valid list structure in Common Lisp. A "dotted pair" must have only one element after the dot. If you want to know more about it, look at your favorite Common Lisp Book how lists are build from cons cells. (For example Peter Seibels "Practical Common Lisp")
So you cannot parse this string as a list as such - you need to have a pre-processing step.
(defun pre-processing (str)
(let ((idx (position #\. str)))
(list (read-from-string (concatenate 'string (subseq str 0 idx) ")"))
(read-from-string (concatenate 'string "(" (subseq str (1+ idx)))))))
This function splits your string in two lists that you can process the way you want to.
CL-USER 1 > (pre-processing "(100 30 5 . 50 6)")
((100 30 5) (50 6))