suppose we are given a 4-tuple (1,2,3,"cookies") and like to map it to a smaller tuple (1,2,3). How can this mapping be achieved? Is there something like a 'slice' function as in e.g. python?
Also another question in this context: how can string like e.g. "1.5" be converted into a float 1.5? Is there something like a 'toFloat' function?
--> found here a solution. My apologies for the insufficient research in stackoverflow. (see: Turn string into number in Racket)
Thank you for any hints
You could always create your own function, a sort of "my-4-tuple-to-3-tuple" function that just makes a new tuple based on the old one. This is bad if you have a lot of different 4 tuples though because it's not a very generic solution.
For example... if you represent your tuple as a list.
(define (4tuple-to-3tuple 4tuple)
(list (first 4tuple) (second 4tuple) (third 4tuple))
I have no actually used it on a decimal but you can use
(string->number "1.5") it should work, however there might be a number to real or nunber to float tho
Use drop and take.
If you need to remove something from the end of a list, do something like this:
`(reverse (drop (reverse xs) 5)`
Use rest to remove a single element:
`(reverse (rest (reverse xs))`
Note that single linked lists are a bad representation choice if you need to manipulate the end of the list often.
To convert a string into a number, use string->number.
Docs on drop:
http://docs.racket-lang.org/reference/pairs.html?q=drop
Docs on string->number:
http://docs.racket-lang.org/reference/generic-numbers.html?q=string-%3Enumber
use vector instead of tulip
use vector-copy to get splice
the link to vector: http://docs.racket-lang.org/reference/vectors.html
Related
I want to preface this by saying that yes, this is a homework problem I'm working on and I don't want the actual answer, just maybe a nudge in the right direction. Anyhoo, I'm taking a class on programming languages' structures, and one of our projects is to write a variety of small programs in lisp. This one requires the user to input a list and an atom, then remove all instances of the atom from the list. I've scoured the internet and haven't found all that many good lisp resources, so I'm turning to you all.
Anyways, our professor has given us very little by way of stuff to work off of, and by very little I mean practically nothing.
This is what I have so far, and it doesn't work.
(defun removeIt (a lis)
(if (null lis) 0
(if (= a (car lis))
(delete (car lis))
(removeIt (cdr lis)))))
And when I type
(removeIt 'u '(u e u e))
as the input, it gives me an error stating it got 1 argument when it wanted 2. What errors am I making?
First, a few cosmetic changes:
(defun remove-it (it list)
(if (null list) 0
(if (= it (car list))
(delete (car list))
(remove-it (cdr list)))))
Descriptive and natural sounding identifier names are preferred in the CL community. Don't be shy to use names like list – CL has multiple namespaces, so you don't have to worry about clashes too much. Use hyphens instead of camel case or underscores. Also, read a short style guide.
You said you didn't want the answer but helpful tips, so here we go:
Check your base case – your result will be a list, so why do you return a number?
Use the appropriate comparison function – = is for numbers only.
You are building a new result list, so no need to delete anything – just don't add to it what you don't want.
But remember to add what you want – build your result list by consing what you want to keep to the result of applying your function to the rest of the list.
If you don't want to keep an element, just go on applying your function to the rest of the list.
You defined your function to take two arguments, but you're calling it with (cdr list) only. Provide the missing argument.
I've scoured the internet and haven't found all that many good lisp
resources,
Oh, come on.
Anyhow, I recommend Touretzky.
By the way, the function you're trying to implement is built-in, but your professor probably won't accept it as a solution, and doing it yourself is a good exercise. (For extra credit, try solving it for nested lists.)
This is a good case for a recursive function. Suppose there exists already a function called my-remove which takes an atom and a list as arguments and returns the list without the given atom. So (my-remove 'Y '(X Y Z)) => '(X Z)
Now, how would you use this function when instead of the list '(X Y Z) you have another list which is (A X Y Z), i.e. with an element A in front?
You would compare A to your atom and then, depending on whether the element A matches your atom, you would add this element A or not to the result of applying remove to the rest of the list.
With this recursion the function my-remove will be called successively with shorter lists. Now you only have to think about the base case, i.e. what does the function my-remove have to return when the list is empty.
This is an answer for other people looking specifically for elisp. A builtin function exists for this purpose called delq
Example
(setq my-list '(0 40 80 40 90)) ;; test list
(delq 40 my-list) ;; (0 80 90)
If you installed emacs from source you can check out how it is implemented by doing Mx find-function delq
In Common Lisp, the let uses a list for a bindings, i.e:
(let ((var1 1)
(var2 2))
...)
While Clojure uses a vector instead:
(let [a 1
b 2]
...)
Is there any specific reason, other than readability, for Clojure to use a vector?
You can find Rich Hickey's argument at Simple Made Easy - slide 14, about 26 minutes in:
Rich's line on this was as follows
"Since we were talking about syntax, let’s look at
classic Lisp. It seems to be the simplest of syntax, everything is a
parenthesized list of symbols, numbers, and a few other things. What
could be simpler? But in reality, it is not the simplest, since to
achieve that uniformity, there has to be substantial overloading of
the meaning of lists. They might be function calls, grouping
constructs, or data literals, etc. And determining which requires
using context, increasing the cognitive load when scanning code to
assess its meaning. Clojure adds a couple more composite data literals
to lists, and uses them for syntax. In doing so, it means that lists
are almost always call-like things, and vectors are used for grouping,
and maps have their own literals. Moving from one data structure to
three reduces the cognitive load substantially."
One of the things he believes was overloaded in the standard syntax was access time. So vector syntax in arguments is related to the constant access time when you used them. He said:
Seems odd though as it only is valid for that one form...as soon as it is stored in a variable or passed in any way the information is 'lost'. For example...
(defn test [a]
(nth a 0)) ;;<- what is the access time of and element of a?
I personally prefer harsh syntax changes like brackets to be reserved for when the programmer has to switch mental models e.g. for embedded languages.
;; Example showing a possible syntax for an embedded prolog.
{size [],0}
{size([H|T],N) :- size(T,N1), N is N1+1}
(size '(1 2 3 4) 'n) ;; here we are back to lisp code
Such a concept is syntactically constant. You don't 'pass around' structure at runtime. Before runtime (read/macro/compile time) is another matter though so where possible it is often better to keep things as lists.
[edit]
The original source seems to have gone, but here is another record of the interview: https://gist.github.com/rduplain/c474a80d173e6ae78980b91bc92f43d1#file-code-quarterly-rich-hickey-2011-md
In Clojure, what is the idiomatic way to validate that a value is one of a set of possible values?
I initially did something like this:
(let [size :grande]
(make-latte (condp = size
:tall :tall
:grande :grande)))
The above is useful because if no clause matches an IllegalArgumentException is thrown.
But then I found this more comfortable to do:
(let [size :grande]
(make-latte (or (some #{:tall :grande} [size])
(throw (IllegalArgumentException. "I don't know that size")))
This technique works well because it allows for more possible values, e.g.
(some #{:short :tall :grande :venti} [size])
What's the best way to do this? Am I right in thinking that clojure.core does not have a function that does this already?
(some #{:short :tall :grande :venti} [size])
is equivalent to
(#{:short :tall :grande :venti} size)
That's because sets are functions. For a generic collection you can use contains?.
Edit: as user1571406 notes below, be aware that contains? tests for keys, not values.
You could use a pre-condition in the make-latte function itself. See https://stackoverflow.com/a/8607359/609639
Problem:
Suppose I have a set of functions f_1 ... f_n that I want to compose at runtime, such that I get for example:
(f_a (f_b (f_c) (f_d)) (f_e))
Therefore I need the types of the parameters and the return value of each function in order to know, which functions I can plug into each other.
First Attempt: Annotate each function
(defn foo [n f]
^{:params [Number clojure.lang.Fn]
:return String}
(do stuff with f and n, return a string))
I don't like this approach because of obvious reasons, such as if I wanted to use clojure.core as the set of functions I would have to annotate every function, which wouldn't be very desirable.
Questions
How would you attempt to solve this problem?
Could core.typed help me with that?
I do similar things when composing the search query to pass to solr and use a map for the arguments to all the functions and have them all return a map with whatever changes the function decided to make contained in the map, and everything else returned unchanged. So in short i would:
use a map for the input and output of every function
core.typed is not helpful because everything is a map
prismatic.schema is very helpful because you can use it to know what keys are required and to write tests that validate the structure of these maps.
Projects/people with more of an inclination to statically typed functional languages will likely turn to monads in cases like this because they are a powerful tool for describing composition in a type safe way.
This is a follow up to my question "Recursively reverse a sequence in Clojure".
Is it possible to reverse a sequence using the Clojure "for" macro? I'm trying to better understand the limitations and use-cases of this macro.
Here is the code I'm starting from:
((defn reverse-with-for [s]
(for [c s] c))
Possible?
If so, I assume the solution may require wrapping the for macro in some expression that defines a mutable var, or that the body-expr of the for macro will somehow pass a sequence to the next iteration (similar to map).
Clojure for macro is being used with arbitrary Clojure sequences.
These sequences may or may not expose random access like vectors do. So, in general case, you do not have access to the last element of a Clojure sequence without traversing all the way to it, which would make making a pass through it in reverse order not possible.
I'm assumming you had something like this in mind (Java-like pseudocode):
for(int i = n-1; i--; i<=0){
doSomething(array[i]);
}
In this example we know array size n in advance and we can access elements by its index. With Clojure sequences we don't know that. In Java it makes sense to do that with arrays and ArrayLists. Clojure sequences are however much more like linked lists - you have an element, and a reference to next one.
Btw, even if there were a (probably non-idiomatic)* way to do that, its time complexity would be something like O(n^2) which is just not worth the effort compared to much easier solution in the linked post which is O(n^2) for lists and a much better O(n) for vectors (and it is quite elegant and idiomatic. In fact, the official reverse has that implementation).
EDIT:
A general advice: Don't try to do imperative programming in Clojure, it wasn't designed for it. Although many things may seem strange or counter-intuitive (as opposed to well known idioms from imperative programming) once you get used to the functional way of doing things it is a lot, and I mean a lot easier.
Specifically for this question, despite the same name Java (and other C-like) for and Clojure for are not the same thing! First is an actual loop - it defines a flow control. The second one is a comprehension - look at it conceptually as a higher function of a sequence and a function f to be done for each of its element, which returns another sequence of f(element) s. Java for is a statement, it doesn't evaluate to anything, Clojure for (as well as anything else in Clojure) is an expression - it evaluates to the sequence of f(element) s.
Probably the easiest way to get the idea is to play with sequence functions library: http://clojure.org/sequences. Also, you can solve some problems on http://www.4clojure.com/. The first problems are very easy but they gradually get harder as you progress through them.
*As shown in Alexandre's answer the solution to the problem in fact is idiomatic and quite clever. Kudos for that! :)
Here's how you could reverse a string with for:
(defn reverse-with-for [s]
(apply str
(for [i (range (dec (count s)) -1 -1)]
(get s i))))
Note that this code is mutation free. It's the same as:
(defn reverse-with-map [s]
(apply str
(map (partial get s) (range (dec (count s)) -1 -1))))
A simpler solution would be:
(apply str (reverse s))
First of all, as Goran said, for is not a statement - it is an expression, namely sequence comprehension. It construct sequences by iteration through other sequences. So in the form it is meant to be used it is pure function (without side-effects). for can be seen as enhanced map infused with filter. Because of this it cannot be used to hold iteration state as e.g. reduce do.
Secondly, you can express sequence reversal using for and mutable state, e.g. using an atom, which is rough equivalent (not taking into account its concurrency properties) of java variable. But doing so you are facing several problems:
You are breaking main language paradigm so you will definitely get worse looking and behaving code.
Since all clojure mutable state cells are designed to be thread-safe, they all use some kind of illegal concurrent modification protection, and there is no ability to remove it. Consequently, you will get poorer performance characteristics.
In this particular case, like Goran said, sequences are one of the wide-used Clojure abstractions. For example, there are lazy sequences, which could be potentially infinite, so you just cannot walk them to the end. You certainly will have difficulties trying to work with such sequences with imperative techniques.
So don't do it, at least in Clojure :)
EDIT: I forgot to mention it. for returns lazy sequence, so you have to evaluate it in some way in order to apply all state mutations you do in it. Another reason not to do so :)