I'm trying to write this contract: "accept a function that takes at least one argument, and returns a boolean."
The key thing is that I only care that it returns a boolean, and that it accepts one or more arguments -- for instance, it could be a function accepting a single argument, or a function accepting 2 arguments, and either should be accepted.
Here's what I've tried:
First attempt:
(-> any/c any/c ... boolean?)
Second attempt:
(->* (any/c)
(any/c ...) ; => syntax error
boolean?)
Third attempt:
(->* (any/c)
#:rest (listof any/c)
boolean?)
In each of these cases, it seems the contract is expecting the argument not to just be entailed in the contract specification but to match it exactly. That is, for instance, it must be a function that accepts arbitrarily many arguments instead of "if it's a function accepting 2 arguments, that's fine because I'm accepting functions that take an arbitrary number of arguments."
How does one write such a contract?
Would this work?
(define/contract (f x)
(and/c (unconstrained-domain-> boolean?)
(lambda (p)
(let loop ([n (procedure-arity p)])
(match n
[(? number? n) (>= n 1)]
[(arity-at-least n) (>= n 1)]
[(list xs ...) (ormap loop xs)]))))
#t)
Related
For the expression
(define x (length (range 3000)))
I think it is evaluated to
(define x 3000)
For the expression
(define (f x) (length (range 3000)))
Does it evaluate to the following as well?
(define (f x) 3000)
No, they evaluate to two different procedures, with different bodies. A completely different matter is that when executed, they both will return the same value, namely 3000, ignoring the parameter in both cases. To be clear, the first expression binds f to a lambda (this is how define expands a procedure definition under the hood):
(define f
(lambda (x) (length (range 3000))))
The second expression also binds f to a lambda, but it's a different one:
(define f
(lambda (x) 3000))
Either one will return 3000 when invoked:
(f 42)
=> 3000
But the first one will do more work, it has to create a range and calculate its length, whereas the second one simply returns 3000. Regarding your first example - in the end x will have the same value, and it won't matter how you calculated it. But for the second example, the two fs are different objects, even though the values they calculate are the same.
So I'm slightly confused on an introduction to Racket.
I need to write a function called "extend" that takes an element and a predicate, and "extends" the predicate to include the element. For example:
((extend 1 even?) 1)
#t
((extend 3 even?) 3)
#f
I'm fairly new to the language but I don't understand how to get a function to be used or return as a predicate. Not sure if I'm overthinking it or what.
A function is just a value and extend is just a variable like + and cons that evaluate to a function value. functions can be passed as arguments and you just use whatever name you have given it as if it's a function, by using parentheses, and it just works.
A function returns the value the last expression evaluate to. To get it to be a function it either needs to be a variable that evaluate to a function or a lambda that also evaluate to a function.
(define (double-up fn)
(lambda (value)
(fn (fn value)))) ; see. Just use fn as if it is a procedure
((double-up add1) 4) ; ==> 6
(define add2 (double-up add1))
(add2 4) ; ==> 6
(define error-use (double-up 5)) ; works like a charm
(error-use 4)
; Signals "application: not a procedure"
; since `5` isn't a procedure.
Here is another example which is more similar to your assignment. It takes a number, then returns a function that takes another number and then adds them together. Here I choose to define it locally and then leave it as the last expession so that it becomes the result.
(define (make-add initial-value)
(define (adder new-value)
(+ initial-value new-value))
adder) ; this is the result
((make-add 5) 7) ; ==> 12
A predicate is what we call functions often called in predicate position in conditionals (like if and cond). Thus just a function that either return #t or #f and often bound to variables ending with question mark as a naming convention.
I'm trying to define a function as an argument and then passing a number to that function. It should look like this:
> (function-3 sqrt)
1.7320508075688772
I was thinking of just defining function-3 to equal to 3 but it seems like it doesn't work... this is what I have so far:
(define function-3
(λ (x)
(3)))
I don't know if I'm thinking on the right path...but it would be great if someone can just point me in the right direction. Thanks
You’re close—you just want to apply the argument of function-3 to the number 3, like this:
(define function-3
(λ (x)
(x 3)))
More idiomatically, using the shorthand function syntax, it would probably be written like this:
(define (function-3 f)
(f 3))
(The name f is often used instead of x when the value is a function.)
But why?
Functions in Racket (as in its parent language, Scheme) are just ordinary values. Behind all the parentheses, the syntax for function application is actually extremely simple. Here’s an example scheme expression:
(f a b c)
^ ^^^^^
| |
function expression argument expressions
Note that each of these two roles is an expression. Obviously, the arguments can be expressions, not just variables, since you can do things like this:
> (+ 1 (* 2 3))
7
Notably, though, the function itself can be an expression, too. You can have a form that produces a function, and that expression can be used in a function invocation:
> ((λ (x) (* x 2)) 3)
6
So when you call (function-3 sqrt), the sqrt function itself gets passed into the function and bound to the first argument of the function implementation. Therefore, all you need to do is put that argument in function expression position, and it will be invoked like any other function.
You're so close!
(define function-3
(lambda (x)
(x 3)))
Having
(: f (-> Procedure (Pairof Integer Integer) Boolean))
(define (f comparator pair)
(comparator (first pair) (second pair)))
in TypedRacket, how can I make this function work? The function is supposed to work like this:
(f = '(1 2)) >>>> false.
(f > '(4 2)) >>>> true.
I get following errors:
Type Checker: Polymorphic function first could not be applied to arguments
Type Checker: Polymorphic function second could not be applied to arguments
Type Checker: cannot apply a function with unknown arity
So probably it is the function definition which causes this error but how can I fix this?
Here is a definition that does work for your examples:
(: f (-> (-> Integer Integer Boolean) (Listof Integer) Boolean))
(define (f comparator pair)
(comparator (first pair) (second pair)))
(f = '(1 2)) ; => #f
(f > '(4 2)) ; => #t
You must define the type of the first parameter as function from two integers to a boolean, and the second argument as a list (since you used a list in the call of the function).
This is a simple definition, just to start working with types. Than you can change it to apply the function to values with more general types, like Number instead of Integer, polymorphic functions, etc.
I was trying to write my own put-pixel on (Gdk) pixbuf in Lisp. When I finally realized how I can operate on C pointers in CL, new obstacle came along - (gdk:pixbuf-get-pixels pb) returns me negative number. My question is: can I convert it somehow to a valid pointer? My attempts to use cffi:convert-from-foreign and cffi:translate-from-foreign (what's the difference between them anyway?) failed.
Below is my actual (not working) code:
(defun put-pixel (pixbuf x y r g b)
(let ((p (+ (gdk:pixbuf-get-pixels pixbuf) (* x (gdk:pixbuf-get-n-channels pixbuf)) (* y (gdk:pixbuf-get-rowstride pixbuf)))))
(setf (cffi:mem-aref p :unsigned-char 0) r)
(setf (cffi:mem-aref p :unsigned-char 1) g)
(setf (cffi:mem-aref p :unsigned-char 2) b)))
CFFI:TRANSLATE-FROM-FOREIGN is a generic function. You can define your own foreign types using CFFI:DEFINE-FOREIGN-TYPE and then add a method to CFFI:TRANSLATE-FROM-FOREIGN to specify how the conversions from foreign to Lisp values should work.
CFFI:CONVERT-FROM-FOREIGN is what you should call if you need to explicitly convert some value. It will call CFFI:TRANSLATE-FROM-FOREIGN behind the scenes and it might perform some compile-time optimizations if possible.
Same thing applies to CFFI:CONVERT-TO-FOREIGN and CFFI:TRANSLATE-TO-FOREIGN.
I think that lambda-gtk incorrectly defined binding for pixbuf-get-pixels.
The negative value for pointer value might appear because of incorrect interpretation of unsigned integer as a signed integer.
The simplest way to correct this value is to use mod:
CL-USER> (mod -1 (expt 2 #+cffi-features:x86 32 #+cffi-features:x86-64 64))
4294967295