<aeth>
tsizz: You can think of quote as having the distributive property (like a * (b + c) in algebra). So '(a b c d e) is the same thing as (list 'a 'b 'c 'd 'e)
<tsizz>
aeth: mhm i did see that in my research
<tsizz>
i dont get the point of it though
<aeth>
(It's often not entirely equivalent in Lisps/Schemes and I'm not sure about the edge case(s) in Racket if there are any, but it's still a useful model to have in mind.)
<aeth>
tsizz: What's going on is that 'a is a symbol. If you're used to other scripting languages, that's usually the role of a string like "a" and if you're used to non-scripting languages that's usually the role of an enum like A
<aeth>
For things like (define (foobar foo) (if (eq? foo 'a) 42 0))
<aeth>
It's not a character because you can easily have 'knight just like you can have the string "knight" or the enum knight in some chess-related program.
ng0 has quit [Quit: Alexa, when is the end of world?]
<aeth>
When your chess GUI is at the point where the player is promoting a pawn you could have a procedure select-promotion that has as its valid input 'queen or 'knight or 'bishop or 'rook
<aeth>
You could then validate the user's input with (member choice '(queen knight bishop rook))
ZombieChicken has quit [Ping timeout: 256 seconds]
<aeth>
Then you can do this: (define (promotion-choice? choice) (member choice '(queen knight bishop rook))) (define/contract (select-promotion choice) (-> promotion-choice? any) choice)
<aeth>
Obviously you'd want to actually do the promotion logic instead of just returning the choice, but the key part here is that it's a contract violation to not provide 'queen or 'knight or 'bishop or 'rook as input to the function
ZombieChicken has joined #racket
<aeth>
the (-> promotion-choice? any) part in define/contract is the only thing define/contract adds over define and it's just using promotion-choice? as the predicate to check the input
<aeth>
Anyway, the important thing is that you would call (select-promotion 'queen) just like you would do select_promotion("queen") in some languages.
<aeth>
tsizz: I hope that helps where you'd idiomatically see 'foo in use. (You also see it in macros, of course, but that's more advanced.)
amz3 has quit [Ping timeout: 250 seconds]
<tsizz>
aeth: any chance u can look at my code? im so lost where im going wrong. its a simple function!
<tsizz>
basically i am trying to iterate over this list of chars and assign an integer to each char and multiply them together
<tsizz>
im probably just bad at recursion :\
<aeth>
tsizz: The first thing that immediately comes to mind is style issues. Style is pretty uniform in the Lisp/Scheme world so styles that don't fit are much harder to read than in most languages. Notably, ) never goes on its own line and kebab-case is always used over camelCase or underscore_case
<tsizz>
aeth: ok gotcha ty
<aeth>
Also it's (* foo\n bar), not (*\n
<aeth>
tsizz: what's ctv?
acarrico has quit [Ping timeout: 252 seconds]
<tsizz>
aeth: its a function that just gives each character a integer value
<tsizz>
hashing
<tsizz>
(*/n
<tsizz>
you mean like
<tsizz>
(*
<tsizz>
8 9)
<tsizz>
wouldn't work
<aeth>
tsizz: Generally, when you go recursively over a list you don't use indices because that's an O(n) operation. What you do is you pass on the cdr and act like it is the list. So the first iteration would have '(a b c d e) and then the next would have '(b c d e) and the next would have '(c d e) etc. all the way down to '() which is the usual terminating condition
<aeth>
Lists in Lisp/Scheme/Racket are linked lists, unlike in e.g. Python. If you have to use indices, consider using vectors instead, but obviously this is a list task.
<tsizz>
aeth: mhm
<tsizz>
im more worried about funcationality rn
hjek has joined #racket
<aeth>
tsizz: If you have time, I recommend reading through the first parts of The Little Schemer
<aeth>
That does a better job of explaining this kind of function structure than I can
<aeth>
tsizz: Either way, I would recommend starting with something simpler that works and building up to the desired functionality
<tsizz>
aeth: hm can i do this using higher order functions
<tsizz>
for lists
<tsizz>
probably not if ic ant use set
<tsizz>
is what imt hinking
<aeth>
tsizz: I would start with this: (define (foo l n) (if (null? l) (begin (display "Done!\n") '()) (begin (display n) (display " ") (display l) (display "\n") (foo (cdr l) (+ 1 n)))))
<aeth>
That's about as simple as you can get with a list and a counter, except I added display calls in there so you can more easily see what's going on in every step
<aeth>
The begin just lets you do more than one thing in an if clause since it's normally (if condition then else)
<tsizz>
hm okay
<aeth>
This is the version without printing: (define (foo l n) (if (null? l) '() (foo (cdr l) (+ 1 n))))
<tsizz>
i think my logic is okay though
<tsizz>
but clearly not bc something is going wrong
<aeth>
This is an example call: (foo '(a b c d e) 0)
<aeth>
Notice that foo doesn't do anything once you remove the printing, except return a '(), so you're going to have to add some additional logic there, either in return values or as an additional argument
<tsizz>
aeth: yeah how do you do return values o.o
<aeth>
tsizz: The easiest way to do it is to actually build up the answer in another argument and return it instead of '() as the final return value, like this: (define (foo l n answer) (if (null? l) answer (foo (cdr l) (+ 1 n) (list* (cons n (car l)) answer))))
<aeth>
And called like this: (foo '(a b c d e) 0 '())
<aeth>
You might want a helper procedure like (define (foobar l) (foo l 0 '()))
<aeth>
Then you can just (foobar '(a b c d e))
<aeth>
Notice that when you build things up this way you build them up backwards. I get '((4 . e) (3 . d) (2 . c) (1 . b) (0 . a))
<aeth>
But if you do (define (foobar l) (reverse (foo l 0 '()))) then you get '((0 . a) (1 . b) (2 . c) (3 . d) (4 . e)) from (foobar '(a b c d e))
acarrico has joined #racket
<aeth>
Notice that when you write in this style you have to keep track of a shrinking list, an incrementing counter, and a growing list, and then you have to reverse the list at the end if order matters.
<aeth>
Also keep in mind that the letters there are symbols, not characters. I could just as easily have used '(aa bb cc dd ee) as the input.
keep_learning_M has joined #racket
<tsizz>
aeth: i figured my recursion was logic
<tsizz>
i was trying to emulate key += 29 * key + cvt(c)
<tsizz>
as in key += 29 * previous key + cvt(c)
<tsizz>
i don't think my recusrive calls were doing that
<aeth>
tsizz: It's the same principle as my latest foo, except now you need yet another argument to the recrusive procedure in addition to answer
<aeth>
In this case, something like previous-key
<aeth>
The basic principle behind this should scale to basically anything you need: (define (foo l n answer) (if (null? l) answer (foo (cdr l) (+ 1 n) (list* (cons n (car l)) answer)))) (define (foobar l) (reverse (foo l 0 '()))) (foobar '(a b c d e))
<aeth>
It's just that now you'd do (foo l n previous-key answer) and then you'd do the recursive call as (foo (cdr l) (+ 1 n) current-key (list* ... answer))
<aeth>
You can also use cons instead of list*, it's just that cons only lets you append one thing in front and list* lets you append as many as you want in front
<aeth>
cons is probably the more traditional form of this
<aeth>
tsizz: Basically, instead of setting (+=) you build up a new version for the next iteration when you're tail calling. So you basically do all of the +=s in one line, if that makes any sense
<aeth>
The tail call is not too different from this: l = cdr(l); n += 1; previous-key = current-key; answer = list*(..., answer);
catonano_ has joined #racket
catonano has quit [Ping timeout: 245 seconds]
catonano_ is now known as catonano
hjek has quit [Read error: Connection reset by peer]
<aeth>
(In fact, you won't notice a difference unless you make a closure.)
acarrico has quit [Ping timeout: 245 seconds]
hjek has joined #racket
hjek has quit [Remote host closed the connection]
hjek has joined #racket
orivej has quit [Ping timeout: 255 seconds]
hjek has quit [Remote host closed the connection]
iyzsong has joined #racket
efm has quit [Read error: Connection reset by peer]
efm has joined #racket
ubLIX has quit [Quit: ubLIX]
dddddd has quit [Remote host closed the connection]
pie__ has joined #racket
pie___ has quit [Ping timeout: 245 seconds]
_whitelogger has joined #racket
badkins has quit [Ping timeout: 252 seconds]
_whitelogger has joined #racket
_whitelogger has joined #racket
FreeFull has quit []
lavaflow_ has quit [Read error: Connection reset by peer]
jcowan has quit [Quit: Connection closed for inactivity]
ym555 has quit [Ping timeout: 250 seconds]
ym555 has joined #racket
logicmoo is now known as dmiles
ubLIX has joined #racket
<tsizz>
can you add to a list oo.o
<tsizz>
i want to recursively add different numbers to a list
<tsizz>
ah append okay lol
badkins has joined #racket
notzmv has quit [Ping timeout: 240 seconds]
jcowan has joined #racket
<rain1>
How do I make text in the repl that you can click on and something happens?
<rain1>
like: [red] or [blue] and it calls a different procedure for each color
notzmv has joined #racket
<aeth>
tsizz: append adds list to list, cons adds an item to the front of a list, and list* adds multiple items to the front of a list. You probably want one of the latter two
Fare has joined #racket
<aeth>
If the order is reverse from what you want, just reverse it in the end. It will (afaik) be better than continually appending to the end
<tsizz>
aeth: idk about this dot thing though
<aeth>
tsizz: lists don't actually exist, they are actually just syntactic sugar for displaying pairs or cons cells. '(1 . (2 . (3 . (4 . (5 . (6 . (7 . ()))))))) => '(1 2 3 4 5 6 7)
<aeth>
tsizz: So if you're seeing a dot that means you accidentally made a "malformed list" in some sense, e.g. '(1 . (2 . (3 . (4 . (5 . (6 . 7)))))) => '(1 2 3 4 5 6 . 7)
<aeth>
lists have to end in '()
<tsizz>
aeth ah okay
<aeth>
It's a singly linked list, if you're familiar with that data structure
<aeth>
That's also why it's very cheap to add to the front but expensive to add to the end
<tsizz>
aeth: so i am iterating over something and calculating number and adding to a list. would i have to initalize a list or something?
<aeth>
tsizz: you initialize the list as '() and then add to the front of it with cons (or list* if you need to add more than one thing), like (cons 42 '()) => '(42)
<aeth>
This builds it backwards so if order matters you have to reverse at the end
YuGiOhJCJ has quit [Quit: YuGiOhJCJ]
<aeth>
(there are ways around that but that's more advanced than what you're doing)
<tsizz>
aeth: it doesn't save the list tho
<aeth>
tsizz: Any reference to the old list is still referring to the '() since '(42) i.e. '(42 . ()) is a new object whose tail contains the old object.
<tsizz>
hmm okay
<tsizz>
how would i go about keep reference to list so i can return it
<aeth>
If you're going recursively, you need a new argument to your procedure. (foo ... (cons 42 l) ...) will make it so that the l the next time through is now '(42) instead of '()... and if you run that multiple times you'll get '(42 42 42 42 42 42) etc.
<aeth>
You can also just cons it on the return value but then it's no longer tail recursive, like this: (cons 42 (foo ...))
<tsizz>
aeth: i am actually trying for-each this time
<aeth>
tsizz: Then you need a variable around the for-each for your result that is continuously updated
<aeth>
(let ((l '())) ...) where your code goes to the ... and somewhere in your code (set! l (cons 42 l))
<aeth>
l here is the result you're building, if you already have an l call it result or whatever
<tsizz>
aeth: ah were not allowed to use set! :(
<aeth>
Then you're forced to be recursive
<aeth>
That tends to be the case in classes
<tsizz>
dang okay i thought so.
<tsizz>
im just so bad with recursion
<aeth>
There might be some other Racket-specific ways to build lists that could work in your case but I doubt that would be in the spirit of the assignment
<aeth>
although depending on what you're doing, map could work
<tsizz>
aeth: hm perhaps
Fare has quit [Ping timeout: 244 seconds]
<tsizz>
aeth: i have a dictionary of words that i have to hash which sounds perfect
<tsizz>
i hope this is the same map as in javascript or python
<aeth>
Scheme had it first
<tsizz>
interesting
<aeth>
It's not quite the same as in Python 3. It's list->list, and it's list in the linked list sense. Python's "lists" are more like Racket's vectors. I think Python 3's map returns a lazy data structure, too, not just an updated copy with the lambda applied
<tsizz>
aeth: oh i have to use the reduce function too
<tsizz>
or the one he gave us
<tsizz>
i guess i can just make a new list and add to it instead of map the dictioanry words to numbers
<tsizz>
to be safe
<tsizz>
oh but that means i have to use recursion -_-
Sgeo_ has quit [Read error: Connection reset by peer]
Sgeo has joined #racket
<tsizz>
aeth: can i add multiple variables to lambda in for-each?
<tsizz>
or does it only accept 1 for element
<tsizz>
but then i can't make a list..?
<tsizz>
without set
<tsizz>
(define y (cons 5147 y))
<tsizz>
maybe i can try this
<aeth>
tsizz: multiple variables means multiple lists iirc
<aeth>
oh, that's map, sorry
<tsizz>
aeth: im okay on the for each question i can make it work with the element variable only if i put the for-each in a lambda
<aeth>
let me verify if it works on for-each
<tsizz>
hopefully thats okay tho
<aeth>
Compare (for-each (lambda (a b c) (display a) (display " ") (display b) (display " ") (display c) (display "\n") (+ a b c)) (list 1) (list 2) (list 3)) and (map (lambda (a b c) (display a) (display " ") (display b) (display " ") (display c) (display "\n") (+ a b c)) (list 1) (list 2) (list 3)) in the REPL. The difference is that map returns a value and for-each only has side effects.
<tsizz>
i think i got it to work, but im not sure how to return variables really
<aeth>
Also notice that lambda with multiple variables takes in multiple lists, in this case 3
<aeth>
It says for-each is used for its effect and its result is ignored
<aeth>
You probably want map or a similar form on that page that has a result
<aeth>
If you can't use set! then forms used just for their side effects are entirely useless
`micro has quit [Ping timeout: 246 seconds]
<tsizz>
aeth: okay can i use map just like for each
<tsizz>
as in i map each element to get access to element, but not actually change it...?
<tsizz>
im trying to do something forEach hash function in list of hash functions
`micro has joined #racket
<aeth>
map is afaik identical to for-each except it returns a new list with the return value of the function given
<aeth>
Racket lists are immutable
<tsizz>
aeth: so i have to redefine my list when adding stuff right?
<tsizz>
or define it again rather* not redefine
<aeth>
Procedures like map do it for you. You don't build the list step-by-step like in the recursive functions. You return a whole new list at once, e.g. (map (lambda (x) (+ 3 x)) '(1 2 3)) => '(4 5 6) and (map + (list 1 2 3) (list 9 8 7)) => '(10 10 10)
<aeth>
So you don't even need to define a binding and add stuff to it, since the procedure is probably doing that in its intermediate steps, internally.
tilpner has quit [Quit: WeeChat 2.4]
<tsizz>
aeth: but i dont want to change the element
<aeth>
Lisps/Schemes/Racket are expression-oriented, so almost everything will have a meaningful return value. No need to think in terms of bindings if you don't have to.
<tsizz>
aeth: i just want to use the element
<tsizz>
for example (map (lambda (x) (cons (+ x 5) NEWLIST)))
<tsizz>
kind of thing
<aeth>
In (map (lambda (x) (+ 3 x)) '(1 2 3)) when '(4 5 6) is returned, a new fresh '(4 5 6) is allocated according the rule that it was given (add 3) and the original '(1 2 3) still exists in memory. Since there is no other reference to it, it will eventually be garbage collected.
<aeth>
If you want a new list, you name the result. It's an expression.
<tsizz>
mhm
<tsizz>
but i want this new list to exist over iterations of the other list
<aeth>
just like you would do foo = map(...) in another language you do (let ((foo (map ...))) ...) in Scheme or Racket
<tsizz>
aeth: oh how come i use let
<aeth>
let is for local bindings of a variable name. Scope in a Lisp is explicit. The let is the explicit scope object. The new bindings, created in the first part of the let, exist within the body of the let.
<aeth>
instead of saying var foo = 42; var bar = 43; ... you explicitly create the new scope (let ((foo 42) (bar 43)) ...) and carry on within the let. You can also, in Scheme, use (define foo 42) and (define bar 43) at the top of a function, but that just implicitly creates a new let so I don't like it. It's kind of magic.
hjek has joined #racket
<aeth>
You don't normally need to use let. Since everything is an expression and most things return meaningful values, you usually just compose expressions, like you would with (x + y) * z in another language. You don't need to name x + y. Similarly, (* (+ x y) z) in Racket. It's just that a lot more than just arithmetic and logic are expressions. Practically everything is.
<tsizz>
aeth: i did get the correct lists! hm wrong values though
<tsizz>
aeth: i do intend to review scheme bc midterm, but im just behind rn and have hw due so im like rushing
<tsizz>
don't get me wrong i do want to learn it and do it properly, but ya im just in a rush for now haha
vraid has joined #racket
<tsizz>
aeth: do you mind reviewing a recurisve function of mine
<tsizz>
aeth: ok i just changed it to map too lol
<tsizz>
aeth: how often do scheme users use higher order functions vs. recursion?
<aeth>
tsizz: In real code? You (or at least I) almost always use someone else's function(s). A recursion might be some very broad high level loop thing, like an application loop at the topmost level. Or something so fancy that a built-in won't work, like parsing. So, strangely enough, just for the simplest loops and the most advanced.
<aeth>
tsizz: In academic-for-assignment Scheme? Afaik it's like 90% recursion.
<aeth>
It's mostly taught to teach recursion, not Scheme.
<aeth>
Then at the end they usually say "hey here's map and reduce, look at how much work they save"
<tsizz>
aeth: well my class isn't teaching scheme its teaching programming languages and in this case functional
<aeth>
Sort of like how in differential calculus you start with the slow limits and then do the shortcuts later
<tsizz>
question is if higher order functions are considered functional programming, which i think they are because I code some javascript, but not entirely sure why
<aeth>
What functional programming is depends on who you ask. It could mean something as broad as first class functions or it could mean... basically just Haskell.
<aeth>
Pure functional programming (to some, the One True™ functional programming) doesn't mutate state or have side effects. This is e.g. Racket's map. Most Lisp programs are written in some "mostly functional" style, where you use the expression-oriented nature of the language to have a lot less setting/state than in most languages, but you do wind up doing some mutation and setting.
orivej has quit [Ping timeout: 245 seconds]
tilpner has joined #racket
amz3 has quit [Ping timeout: 246 seconds]
<aeth>
Haskell gets around the necessity to do some impurities with monads. Don't ask me about monads. I don't know monads. I know Lisps.
orivej has joined #racket
<tsizz>
aeth: before i read what u say. how do i append this list together if i dont have a refernce
<aeth>
Oh, one more thing, in Scheme you can tell if it's a "destructive" (functionally impure) procedure by the ! at the end, so if it's "map" and not "map!" you can safely know that you're not actually setting anything.
<tsizz>
ah okay
<tsizz>
i have a return of list of lists
ng0 has quit [Quit: Alexa, when is the end of world?]
<tsizz>
so im trying to make it one list
<aeth>
tsizz: '((a b c) (d e f)) => '(a b c d e f) ?
keep_learning_M has joined #racket
<tsizz>
aeth: ?
<tsizz>
its the samething?
<aeth>
I was asking if you wanted to do that operation
<aeth>
(flatten '((a b c) (d e f))) or (apply append '((a b c) (d e f))) gets you '(a b c d e f)
<aeth>
sorry, my syntax in that question was poor
<tsizz>
oh yeah i do
orivej has quit [Ping timeout: 245 seconds]
orivej has joined #racket
<tsizz>
aeth: worked liek a charm thanks
<tsizz>
those are definitely in javascript too lol
<tsizz>
nice to learn functional so i better understand my main language too
<tsizz>
JavaScript was influenced by programming languages such as Self and Scheme.[13] wiki
<aeth>
Well, yes, at some point the "JavaScript is basically a Scheme" meme had to be reinforced by actually adding functions from Scheme :-p
<tsizz>
haha
<tsizz>
didn't know that was a meme
<tsizz>
i wonder where i should use reduce here..
<aeth>
Depending on what you're doing you might be able to manually build the list in reduce instead of map and save the flatten step at the end.
<aeth>
(apparently base racket doesn't have reduce, but it's probably buried in a library somewhere, possibly under the name fold instead of reduce, depending on what you want semantically... this part is complicated because names and APIs vary)
<tsizz>
our teacher wrote us a reduce function and i improted it
<tsizz>
we have to use it once
<aeth>
tsizz: You can probably use your reduce to bring the lists together, or build the lists together and skip the flatten step. I would have to do some thinking about it in order to see how, and that might be the point of your assignment so even if I get the correct answer I'm not sure I should say how.