I'd like to collect various functions in a sequence and activate them by the sequence index, like in this simple example:
mul2: func [n] [2 * n]
mul3: func [n] [2 * n]
...
(pick [mul2 mul3] 1) 2 ; yields 2
It seems that mul2 is not treated like a function when it's referred to as a sequence item:
type? (pick [mul2] 1) == word!
Is it possible to arrange functions into sequences?
While experiencing with this example, I noticed that
function? mul2
complains that the argument of mul2 is missing, instead of returning true. Where am I wrong?
mul2 and mul3 are just words
mul2: func [n] [2 * n]
mul3: func [n] [3 * n]
w: pick [mul2 mul3] 1
type? w
; == word!
When you get it's value, then you'll have the function:
f: get pick [mul2 mul3] 1
; == func [n][2 * n]
type? :f
; == function!
function? :f
; == true
Notice that I used :f (get-word) to get the unevaluated value (the function itself) instead of f, because f will be evaluated and will require its parameters.
And then you can use f:
f 6
; == 12
Related
>> f: func [x /a][either a [x + 2] [x + 1]]
== func [x /a][either a [x + 2] [x + 1]]
>> b: /a
== /a
>> f/b 1
*** Script Error: f has no refinement called b
*** Where: f
*** Stack: f
>> f/:b 1
*** Script Error: f has no refinement called :b
*** Where: f
*** Stack: f
You can see that the function f has a refinement a, and I bind /a to b. When calling f with its refinement /a by b, it fails.
What is the correct way to pass a refinement which needs to be evaluated before to its function? Or, is there a way to convert a path! to function!?
Refinements are limited, in a way that they can be passed only by being listed literally in a function call. On the other hand, you can construct such function call (a path! value followed by all the arguments) whichever way you want:
>> b: 'a
== a
>> do probe reduce [to path! reduce ['f b] 1]
[f/a 1]
== 3
Note that elements of the path in this case are word!s, not refinement!s. In general, such use-case is covered by apply. However, only Rebol has it natively, and with an awkward calling convention:
>> f: func [x /a][either a [x + 2] [x + 1]]
>> b: yes
== true
>> apply :f [1 b]
== 3
>> apply :f [1 no]
== 2
You can easily write your own high-level version of it if that's what you need.
I want to convert many decimal numbers available as strings to floats in one go. I am trying following code which combines these strings into a series and then convert them to floats. This works all right but fails if there is an error:
a: "1.5"
b: ""
c: "3.7"
invars: [a b c]
print a
print type? a
set invars foreach x invars [append [] to-float reduce x] ; code to convert string series to float series;
print a
print type? a
The error is:
*** Script Error: cannot MAKE/TO float! from: ""
*** Where: to
*** Stack: to-float
For error correction, I tried following code:
temp: []
foreach x invars [
y: copy ""
either error? [set [y] to-float reduce x]
[append temp reduce x] ; put original value if not convertable
[append temp reduce y] ]
print temp
set invars temp
print a
print type? a
But this is also not working. Where is the problem and how can this be corrected?
forall invars [invars/1: load get invars/1]
>> invars
== [1.5 [] 3.7]
and if you want to get rid of the empty blocks
>> replace/all invars block! 0
== [1.5 0 3.7]
and if you really want to do all in (:less:) steps
forall invars [invars/1: either empty? invars/1: get invars/1 [0.0] [load invars/1]]
After you can set your variables again.
But if you want just set your variables, you have to do
foreach x invars [set :x load get x]
with to-float
foreach x invars [either empty? get x [set :x 0] [set :x to-float get x]]
and finally an all error safe version with to-float
foreach x invars [attempt [set :x to-float get x]]
== 3.7
>> a
== 1.5
>> b
== ""
>> c
== 3.7
I'm using ghci and I'm having a problem with a function for getting the factors of a number.
The code I would like to work is:
let factors n = [x | x <- [1..truncate (n/2)], mod n x == 0]
It doesn't complain when I then hit enter, but as soon as I try to use it (with 66 in this case) I get this error message:
Ambiguous type variable 't0' in the constraints:
(Integral t0)
arising from a use of 'factors' at <interactive>:30:1-10
(Num t0) arising from the literal '66' at <interactive>:30:12-13
(RealFrac t0)
arising from a use of 'factors' at <interactive:30:1-10
Probable fix: add a type signature that fixes these type variable(s)
In the expression: factors 66
In the equation for 'it': it = factors 66
The following code works perfectly:
let factorsOfSixtySix = [x | x <- [1..truncate (66/2)], mod 66 x == 0]
I'm new to haskell, and after looking up types and typeclasses, I'm still not sure what I'm meant to do.
Use div for integer division instead:
let factors n = [x | x <- [1.. n `div` 2], mod n x == 0]
The problem in your code is that / requires a RealFrac type for n while mod an Integral one. This is fine during definition, but then you can not choose a type which fits both constraints.
Another option could be to truncate n before using mod, but is more cumbersome. After all, you do not wish to call factors 6.5, do you? ;-)
let factors n = [x | x <- [1..truncate (n/2)], mod (truncate n) x == 0]
If you put a type annotation on this top-level bind (idiomatic Haskell), you get different, possibly more useful error messages.
GHCi> let factors n = [x | x <- [1..truncate (n/2)], mod n x == 0]
GHCi> :t factors
factors :: (Integral t, RealFrac t) => t -> [t]
GHCi> let { factors :: Double -> [Double]; factors n = [x | x <- [1..truncate (n/2)], mod n x == 0]; }
<interactive>:30:64:
No instance for (Integral Double) arising from a use of `truncate'
Possible fix: add an instance declaration for (Integral Double)
In the expression: truncate (n / 2)
In the expression: [1 .. truncate (n / 2)]
In a stmt of a list comprehension: x <- [1 .. truncate (n / 2)]
GHCi> let { factors :: Integer -> [Integer]; factors n = [x | x <- [1..truncate (n/2)], mod n x == 0]; }
<interactive>:31:66:
No instance for (RealFrac Integer) arising from a use of `truncate'
Possible fix: add an instance declaration for (RealFrac Integer)
In the expression: truncate (n / 2)
In the expression: [1 .. truncate (n / 2)]
In a stmt of a list comprehension: x <- [1 .. truncate (n / 2)]
<interactive>:31:77:
No instance for (Fractional Integer) arising from a use of `/'
Possible fix: add an instance declaration for (Fractional Integer)
In the first argument of `truncate', namely `(n / 2)'
In the expression: truncate (n / 2)
In the expression: [1 .. truncate (n / 2)]
I am new to Haskell so please forgive my courage to come up with an answer here but recently i have done this as follows;
factors :: Int -> [Int]
factors n = f' ++ [n `div` x | x <- tail f', x /= exc]
where lim = truncate (sqrt (fromIntegral n))
exc = ceiling (sqrt (fromIntegral n))
f' = [x | x <- [1..lim], n `mod` x == 0]
I believe it's more efficient. You will notice if you do like;
sum (factors 33550336)
In sml nj, if you use the map function, your basically saying for each element x in a list, apply the function f on it, and return the list of the new values, but lets say f returns a string, and in f a comparison is done, if the comparison is true, then it returns the string, but if it's false, then it doesn't return anything, and nothing gets put into that list that map is currently building.
Is this possible to do?
Instead of using map, use one of the variants of fold (either foldl or foldr). Another option is, of course, to simply do a filter before you do the map.
As a simple example, imagine that you want to return a list of squared integers, but only if the original integers are even numbers. A filter-then-map approach might look like:
fun square_evens xs =
(List.map (fn x => x * x)) (List.filter (fn x => x mod 2 = 0) xs)
Or, you could use a foldr approach.
fun square_evens xs =
List.foldr (fn (x, xs') =>
if x mod 2 = 0
then (x * x) :: xs'
else xs') [] xs
Slightly longer, but arguably clearer, and probably more efficient.
I want to be able to modify Object dynamically by adding / removing properties or methods on the fly. For Adding no problem, for Removing I thought about using Set Difference Math Operator but it behaves weirdly as far as I can see when removing a method from the object.
For example if I have
O: make object! [
a: 1
f: func [][]
b: 1
]
I can substract [a: 1 b: 1] with no problem
>> difference third O [b: 1 a: 1]
== [f: func [][]]
But I cannot substract f: func[][]:
>> difference third O [f: func[][]]
== [a: 1 b: func [][] func []]
>>
Output is weird (I put strange maybe it doesn't sound english as I'm not english native :) )
Why and what should I do instead ?
Thanks.
Issue #1: Difference Discards Duplicates From Both Inputs
Firstly, difference shouldn't be thought of as a "subtraction" operator. It gives you one of each element that is unique in each block:
>> difference [1 1 2 2] [2 2 2 3 3 3]
== [1 3]
>> difference [2 2 2 3 3 3] [1 1 2 2]
== [3 1]
So you'd get an equivalent set by differencing with [a: 1 b: 1] and [1 a: b:]. This is why the second 1 is missing from your final output. Even differencing with the empty set will remove any duplicate items:
>> difference [a: 1 b: 1] []
== [a: 1 b:]
If you're looking to actually search and replace a known sequential pattern, then what you want is more likely replace with your replacement as the empty set:
>> replace [a: 1 b: 1] [b: 1] []
== [a: 1]
Issue #2: Function Equality Is Based On Identity
Two separate functions with the same definition will evaluate to two distinct function objects. For instance, these two functions both take no parameters and have no body, but when you use a get-word! to fetch them and compare they are not equal:
>> foo: func [] []
>> bar: func [] []
>> :foo == :bar
== false
So another factor in your odd result is that f: is being subtracted out of the set, and the two (different) empty functions are unique and thus both members of the differenced set.
R2 is a little weirder than R3 and I can't get :o/f to work. But the following is a way to get an ''artificially correct-looking version'' of the difference you are trying to achieve:
>> foo: func [] []
>> o: make object! [a: 1 f: :foo b: 2]
>> difference third o compose [f: (:foo)]
== [a: 1 b: 2]
Here you're using the same function identity that you put in the object in the block you are subtracting.
In R3, difference does not support function values in this way. It may relate to the underlying implementation being based on map! which cannot have ''function values'' as keys. Also in Rebol 3, using difference on an object is not legal. So even your first case won't work. :(
Issue #3: This isn't how to add and remove properties
In Rebol 3 you can add properties to an object dynamically with no problems.
>> obj: object [a: 1]
== make object! [
a: 1
]
>> append obj [b: 2]
== make object! [
a: 1
b: 2
]
But as far as I know of, you cannot remove them once they have been added. You can set them to none of course, but the reflection APIs will still report them as being there.
If you want to make trying to read them throw an error you can set it to an error object and then protect them from reads. A variant of this also works in R2:
>> attempt [obj/b: to-error "invalid member"]
== none
>> probe obj
== make object! [
a: 1
b: make error! [
code: 800
type: 'User
id: 'message
arg1: "invalid member"
arg2: none
arg3: none
near: none
where: none
]
]
>> obj/b
** User error: "invalid member"
R3 takes this one step further and lets you protect the member from writes, and even hide the member from having any new bindings made to it.
>> protect 'obj/b
== obj/b
>> obj/b: 100
** Script error: protected variable - cannot modify: b
>> protect/hide 'obj/b
== obj/b
>> obj
== make object! [
a: 1
]
If you need to dynamically add and remove members in R2, you might also consider a data member in your object which is a block. Blocks and objects are interchangeable for many operations, e.g:
>> data: [a: 1 b: 2]
== [a: 1 b: 2]
>> data/a
== 1
>> data/b
== 2
And you can remove things from them...
>> remove/part (find data (to-set-word 'a)) 2
== [b: 2]
It all depends on your application. The main thing object! has going over block! is the ability to serve as a context for binding words...
You cannot dynamically add or remove words from an object in Rebol 2. If you wish to simulate this behaviour you need to create and return a new object.