Simplistic way to think of the apply function - scheme

In trying to 'reduce' the apply function, is the correct a proper understanding?
For example for (apply func args)
Remove the (apply and matching ).
Inset the func as the first element of the args, moving the outer quote in one level if necessary.
Here would be an application:
; (add-pairs '((1 2)(3 4))) --> (3 7)
(define (add-pairs ps)
(if (null? ps) nil
(cons (+ (car (car ps)) (cadr (car ps))) (add-pairs (cdr ps)))))
(apply add-pairs '(((1 2) (3 4))))
xxxxxxx x
; Remove the "(apply " and matching ")"
add-pairs '(((1 2) (3 4)))
------------^
; Insert the function into the args, moving the quote in one level if required.
(add-pairs '((1 2) (3 4)))
Is the above an accurate way to show how the apply gets added in, or am I missing anything?

The example is unfortunate, as it only leaves one argument after "the opening of the parentheses". But yes, that's how I also think about it. The simpler the better, :) as long as it is correct.
Except that of course the values in the list are first evaluated, so it's not a simply-syntactical process. But as a basic example,
(apply + (list 1 2 3))
==
( + 1 2 3 )
i.e. the parens around the arguments is what goes away.
For a non-trivial example, see
Matrix multiplication in scheme, List of lists

It seems like you know Python. I personally think that apply in Scheme and star operator * in Python are quite similar.
Imagine you want to zip several lists, which were themselves packed inside a list. Trying to call
list_of_lists = [[1, 2],[3, 4]]
zip(list_of_lists)
would not give you [(1, 3), (2, 4)], so you write
zip(*list_of_lists)
# here it's the same as
zip(list_of_lists[0], list_of_lists[1])
using the iterable unpacking operator *. A (pretty full) alternative to this in Racket/Scheme is using an apply function:
(define list-of-lists '((1 2) (3 4)))
(apply zip list-of-lists)
;; here it's the same as
(zip (car list-of-lists) (cadr list-of-lists))
(If, of course, zip in Scheme was defined the same way as in Python, requiring arbitrary number of arguments)
But you can definitely see the difference here, the syntactic one. In Python version of apply we are 'applying' this * to arguments and then pass what was 'returned' to calling function (zip). Scheme acts like a functional language and reverses everything inside out (at least that's how I see it): you're 'applying' apply to a function and its arguments and then it handles everything itself.
The other significant difference is that, of course, apply in Scheme is a normal function, so we can write e.g.
(define (apply-func-to-sum-and-args func args)
(func + args))
(apply-func-to-sum-and-args apply (list 1 2 3))
;; returns 6
Though I believe (correct me if I'm wrong) that this function cannot be written in pure Scheme and it calls some weird C function under the hood.

Related

Why is the empty list produced here in this iteration?

Let's take the following function to get a pair of numbers:
; (range 1 3) --> '(1 2 3)
(define (range a b)
(if (> a b) nil
(cons a (range (+ 1 a) b))))
; generate pair of two numbers with 1 <= i < j <= N
(define (get-pairs n)
(map (lambda (i)
(map (lambda (j) (list i j))
(range 1 (- i 1))))
(range 1 n)))
(get-pairs 2)
; (() ((2 1)))
(get-pairs 3)
(() ((2 1)) ((3 1) (3 2)))
Why does the above produce '() as the first element of the output? Comparing this with python, I would expect it to just give the three pairs, something like:
>>> for i in range(1,3+1): # +1 because the range is n-1 in python
... for j in range(1,i-1+1):
... print (i,j)
...
(2, 1)
(3, 1)
(3, 2)
I suppose maybe it has to do with when i is 1?
(map (lambda (j) (list 1 j)) '())
; ()
Is that just an identity in Scheme that a map with an empty list is always an empty list?
When i is 1, the inner map is over (range 1 0), which is () by your own definition. Since map takes a procedure and a list (or lists) of values, applies the procedure to each value in the list in turn, and returns a list containing the results, mapping any procedure over a list containing no values will return a list containing no values.
It might help to create a simple definition for map to see how this might work. Note that this definition is not fully featured; it only takes a single list argument:
(define (my-map proc xs)
(if (null? xs)
'()
(cons (proc (car xs))
(my-map proc (cdr xs)))))
Here, when the input list is empty, there are no values to map over, so an empty list is returned. Otherwise the procedure proc is applied to the first value in the input list, and the result is consed onto the result of mapping over the rest of the list.
A couple of observations:
First, the empty list is not represented by nil in either standard Scheme or vanilla Racket, and you should not be using it. In the early days of Scheme nil was allowed as a crutch for programmers coming from other lisps, but this has not been the case for a long time. I don't think that it was ever in any of the RnRS standards, but nil may have survived in some specific implementations until maybe R4RS (1991). SICP was from that era. Today you should use '() to represent empty list literals in Scheme so that your code can run on any Scheme implementation. Racket's #lang sicp allows code directly from the book to be run, but that should not keep you from using the common notation. Note that Common Lisp does use nil as a self-evaluating symbol to represent both the empty list, and boolean false. Seeing this in Scheme just doesn't look right today.
Second, you will probably be led astray more often than to wisdom by thinking in terms of Python when trying to understand Scheme code. In this particular case, map is an iteration construct, but it is not the same thing as a for loop. A for loop is usually used for side-effects, but map is used to transform a list. Scheme has a for-each form which is meant to be used for its side-effects, and in that sense is more like a for loop. The Python version that is posted above is not at all like the Scheme version, though. Instead of returning the results in a list, the results are printed. In the Scheme code, when i is 1, the inner mapping is over (range 1 0) --> (). But, in the Python code, when i is 1, the inner loop is over range(1, 1), so the body of this for loop is not executed and nothing is printed.
Better to think carefully about the Scheme code you want to understand, falling back on basic definitions, than to cobble together a model based on Python that has possibly unconsidered corner cases.

racket: Why doesn't apply work with "bitmap" function?

I have been cautioned against using eval in my code. However, in this bit of racket code, I can get eval working but not something more recommended, like apply. Here is the code:
(require 2htdp/image)
(define (get_img filename)
(let ([img (eval `(bitmap ,filename))])
(image->color-list mask)
))
I tried doing the naive replace of eval with apply:
(require 2htdp/image)
(define (get_img filename)
(let ([img (apply `(bitmap ,filename))])
(image->color-list mask)
))
and when I run it I get:
; apply: arity mismatch;
; the expected number of arguments does not match the given number
; expected: at least 2
; given: 1
; [,bt for context]
I have tried a few permutations of this code, but to no avail. I was hopeful this one
(let ([img (apply bitmap `(filename))])
(image->color-list img)`)
would work, but clearly there's still something I'm not understanding
EDIT:
The first thing I tried, with error message:
> (require 2htdp/image)
> (define (get_img filename)
(let ([img (bitmap filename)])
(image->color-list img)))
; readline-input:6:15: bitmap: expected a path with a / in it
; in: (bitmap filename)
; [,bt for context]
Another failed attempt:
> (define (get_img filename)
(let ([img (apply bitmap (list filename))])
(image->color-list mask)))
; readline-input:16:20: bitmap: bad syntax
; in: bitmap
; [,bt for context]
You're using it wrong. So behind the variable + there is a procedure object which can be applied. These are equal:
(+ (* 2 3) 5) ; ==> 11
(apply + (list (* 2 3) 5)) ; ==> 11
(apply + `(,(* 2 3) 5)) ; ==> 11
In your example you are using bitmap and it isn't a procedure at all but a macro and it seems it is to get bitmaps from a racket package and with strings it expects at least a slash since images should't be in the package root. You should replace it with bitmap/file which is a procedure and takes a file path absolute or relative to current working directory instead.
In your example (apply `(bitmap/file ,filename) you are passing apply a list as first argument instead of a procedure object and a last argument with parameters.
In your example (apply bitmap/file `(filename)) you are applying bitmap with a literal list with a symbol filename which has nothing to do with the variable with the same name. You were so close since I think you wanted (apply bitmap/file `(,filename)) which is a funny way of doing (apply bitmap/file (list filename)). What I don't understand is why can't you just do this:
(define (get_img filename)
(let ([img (bitmap/file filename)])
(image->color-list mask)))
The combination apply and bitmap doesn't work together because bitmap is not a function. Note that the entry in the documentation on bitmap says "Syntax" and not "procedure".
If f is a function, then (apply f (list a b c)) will compute (f a b c).
However, bitmap is not a function, it is a "special form".
You are in luck though, because bitmap/file is a function, so you can use that instead.
I think it's worth understanding what apply is useful for, in Racket or other Lisp-1s. In almost all code it is useful when you have a function and a bunch of arguments but you don't know how many there are, and you want to call the function with those arguments. What that means in practise is:
'you have a function' so in particular you are not trying to evaluate some macro form or something else special;
'you have a bunch of arguments' means you have a list of arguments.
If you know how many arguments you have then there is almost never a reason to use apply unless the arguments are already in a list and you don't want to bother extracting them: (apply cons l) might be easier than (cons (first l) (second l)) say.
In particular if you are trying to call a function with a single argument which you know then apply is definitely not what you want. And similarly it is never what you want if the 'function' is a macro.
In Lisp-2s there is an additional use for apply: calling a function which is the value of a variable. This is needed because, as a silly example, (let ((x (lambda (...) ...))) ... (x ...) ...) won't work in a Lisp-2. Lisp-2s have an additional function, funcall, which does what apply does when you know the number of arguments: you don't need funcall in a Lisp-1.
The cases where eval is useful are even rarer. There are some, but almost all the time it is at best a confusion and at worst a terrifying security problem: what does
(define (terror x) (eval `(list x)))
Do when it is called? Answer: anything at all that the language is capable of doing: (terror '(launch-the-nukes)), say.

Sum of rows in a matrix with lisp

I'm doing some LISP exercises using functions mapcar and apply. I'm dealing with matrixes, and I have to sum its rows and columns. For column I have:
(apply #'mapcar #'+ matrix)
That works. Since I know how to transpose a matrix, I can do the exact same thing for the rows right? Right, that would be:
(apply #'mapcar #'+ (apply #'mapcar #'list matrix))
But I'm not happy with that. I want to sum the row directly, so I did a mapcar of apply:
(mapcar #'apply #'+ matrix)
that doesn't work and I don't know why. The error is
The value #(FUNCTION +) is not of type LIST.
[Condition of type TYPE-ERROR]
For me, that would get every list inside matrix, and apply the sum in each one. I cannot make a mapcar of apply? If no, why not? Is there another way to sum the rows of a matrix using just mapcar and apply?
PS: I'm using lispstick to compile and the matrix is a list of lists. Example
((1 1 1) (2 2 2) (3 3 3))
for a 3x3 matrix.
Your error
The error you got is from mapcar which expects lists as its arguments after the 1st one, and finds the function + instead.
Solution
What you need is a partial application of apply to +, i.e.,
(defparameter matrix '((1 1 1) (2 2 2) (3 3 3)))
(mapcar (lambda (l) (apply #'+ l)) matrix)
==> (3 6 9)
You can even define a function for that:
(defun partial-application (f &rest some-args)
(lambda (&rest more-args)
(apply f (append some-args more-args))))
(funcall (partial-application #'+ 4) 5)
==> 9
(funcall (partial-application #'+ 1 2) 3 4 5)
==> 15
Now you can use it instead of the lambda:
(mapcar (partial-application #'apply #'+) matrix)
==> (3 6 9)
Notes:
(lambda (l) (apply #'+ l)) and (partial-application #'apply #'+) merely compute the sum of a list, and can be defined in many different ways as discussed elsewhere.
append cannot be safely replaced with the non-consing verson nconc because some-args is not guaranteed to be fresh:
The value of a rest parameter is permitted, but not required, to share structure with the last argument to apply.

Scheme skip or continue during lambda map

I am building a function that takes a set of integers, and returns a subset of the odd integers. I am running into the problem that I need to skip over the even integers in my map, but right now my function returns #<void> instead.
(define (oddSubset set)
(map
(lambda (x)
(cond
((odd? x) x)))
s))
In use:
> (oddSubset '(1 2 3))
'(1 #<void> 3)
Is there logic I can use like "else, continue onto next element"?
Note: I am trying to rewrite the built in filter function
map does not have the possibility to skip, but you can use filter instead:
(filter odd? '(1 2 3 4 5 6)) ; ==> (1 3 5)
Or you can use fold-right
(fold-right (lambda (e acc)
(if (odd? e)
(cons e acc)
acc))
'()
'(1 2 3 4 5 6)) ; ==> (1 3 5)
I assume #!r6rs. Both fold-right and filter are in the library (rnrs lists (6)). There is also SRFI-1 which gives both of these procedures for a R5RS language.
In the none standard language #!racket uses the name foldr in place of fold-right.
map looks like a weird choice for this. By definition it maps a function onto each element in a list and returns the list of the results, so trying to "skip" elements seems unnatural.
filter is what you're looking for.
(filter odd? '(1 2 3))
'(1 3)
map applies a function on all elements. Each invocation of the function is supposed to be independant from the others. Even if you introduce a state with a closure, you can't avoid map to build a list of same size as your input.
You want to (re-)implement the filter function. If you want to do it by yourself, you should try to use foldl and foldr instead.
(cond
((odd? x) x))
map check each element in the list: if it is odd, then return that element. But you did not tell your program what to do when the element is not odd, so map return void.
To solve your problem: use filter instead, since map will return something for each element in the list.
If you want to know how to implement filter, try reading the second chapter of SICP

Issues with evaluating expressions from user input

I'm trying to make a recursive definition that reads and execute user expressions, such as (3 + 5). Everything is working, except of one problem with the arithmetic symbol.
I managed to replicate the error in a simpler example:
(define v '(1 + 3))
((cadr v) 2 4)
The (cadr v) is the + symbol, but for some reason the procedure can't be executed on the two arguments that followed. Am I missing something?
I think that's because
(cadr v)
returns '+ not + (literal + not a + function).
You need to evaluate it before applying it to arguments.
This should work:
((eval (cadr v)) 2 4)
^evaluates the '+ to +
edit
This worked in racket in interactive mode.
I'm not really sure what's the difference, but made it work in r5rs mode in racket (a script):
#lang r5rs
;required by r5rs
(define user-initial-environment (scheme-report-environment 5))
(define v '(1 + 2))
;eval expects a quoted expression
;(it seems that if it's a function it has to have arguments too)
;and evaluation environment.
((eval (cadr v) user-initial-environment) 2 4)
As others have pointed out, the problem is that the list you've constructed contains the symbol plus, rather than the function plus.
At its heart, this is the same reason that '(a b) returns a list of two symbols, rather than signalling an unbound identifier error; the quote starts a term in a "data language" where legal identifiers are interpreted as symbols, rather than as variable references.
The question, of course, is what you should do about it. Some here have suggested using 'eval'; this is probably a bad idea, for reasons that I think Matthew Flatt captures elegantly in his blog post on the topic.
Instead, you should probably write a simple mapping function. Here's the way I'd write it. If you use my code in an assignment, be sure to credit me :).
#lang racket
;; a mapping from symbols to operators
(define operator-hash
(hash '+ +
'- -
'* *))
;; ... and whatever other operators you want.
;; example of using it:
(hash-ref operator-hash '+) ;; ==> +
Try this:
(define v '(1 + 3))
(let ((operator (eval (cadr v)))
(operand1 (car v))
(operand2 (caddr v)))
(apply operator (list operand1 operand2)))
You can do it this way with eval in Guile:
(define (infix-eval v)
(eval (list (cadr v)(car v)(caddr v))
(interaction-environment)))
> (infix-eval '(1 + 2))
3
Rather than using interaction-environment, you could supply another environment for evaluation, where you could also define some other symbols not found in standard Scheme, so that expressions like (7 % 3) and (2 ^ 6) would also work.

Resources