I'm walking through a set of nested blocks and want to stop the walk when I've found the value I'm looking for.
For reasons that are beyond the scope of this question, I can't use PARSE for this particular problem, nor use FOREACH as the looper:
walk: func [series [block!] criteria [block!]][
use [value] compose/deep [
while [not tail? series][
value: pick series 1
either block? value [
walk value criteria
][
(to paren! criteria)
]
series: next series
]
]
]
I'd like to break out if I find this specific value.
walk [a [b c [d e] f] g] [if value = 'e [return value]]
; returns 'e
However, I'd also like to do operations that don't break out:
walk [a [b c [d e] f] g] [
collect [if find [c e] value [keep value]]
]
; returns [c e]
Would like to try and solve this for any of the Rebol flavours including Red. Any thoughts as to efficiency (reason I use a block instead of a function), etc. would be welcome too.
The function combo I was looking for is CATCH/THROW. Once again, using the given function:
walk: func [series [block!] criteria [block!]][
use [value] compose/deep [
while [not tail? series][
value: pick series 1
either block? value [
walk value criteria
][
(to paren! criteria)
]
series: next series
]
]
]
I can simply wrap it as follows:
catch [walk [a [b c [d e] f] g] [if value = 'e [throw value]]]
; returns 'e
Some Notes
I want the function to return NONE if there are no matches
I'll just have WALK return NONE (am using ALSO just so as not to leave an awkward trailing none):
walk: func [series [block!] criteria [block!]][
also none use [value] compose/deep [
while [not tail? series][
value: pick series 1
either block? value [
walk value criteria
][
(to paren! criteria)
]
series: next series
]
]
]
red does not have a USE function
This introduces a complication as I only want to bind the block to the word VALUE. If I were to rewrite the function as follows:
walk: func [series [block!] criteria [block!] /local value][
do bind compose/deep [
while [not tail? series][
value: pick series 1
either block? value [
walk value criteria
][
(to paren! criteria)
]
series: next series
]
] 'value
]
Then it also binds that same block to the words SERIES and CRITERIA which would override the binding of any such words from the calling context, e.g.:
walk [some values][series: none probe value] ; results in error
This version avoids binding anything except VALUE and works in Red 0.6.3 and Rebol2:
walk: func [series [block!] criteria [block!]][
also none do bind compose/deep [
while [not tail? series] [
value: pick series 1
either block? value [
walk value criteria
] [
(to paren! criteria)
]
series: next series
]
]
context [value: none]
]
(Comments on how this implementation differs from what USE does would be welcome.)
And yes, this does not work on Rebol3 Alpha. But neither does the one with the USE. I think it's a THROW issue.
Related
I am using FsUnit.Xunit. I am getting a failure for the following test case:
[<Fact>]
let ``Initialization of DFF`` () =
dff Seq.empty Seq.empty |> should equal (seq {Zero})
The test failure is:
Message:
FsUnit.Xunit+MatchException : Exception of type 'FsUnit.Xunit+MatchException' was thrown.
Expected: Equals seq [Zero]
Actual: seq [Zero]
Stack Trace:
That.Static[a](a actual, IMatcher`1 matcher)
Signal.Initialization of DFF() line 11
I get the same error if the test is:
[<Fact>]
let ``Initialization of DFF`` () =
dff Seq.empty Seq.empty |> should equal (Seq.singleton Zero)
I have never tested equality of sequences using FsUnit.Xunit, so I am confused what's going on. I'm not even for sure what the failure message is telling me, as it seems to be saying that the expected and actual are the same. I can get this to work fine by converting the sequences to lists, but it would be nice to not have to do that.
Could someone explain what's going on here? It seems I'm not understanding the error message and thus probably something about Equals and comparing sequence values (literals?). Thanks.
Source code to be able to reproduce (I think this is everything):
type Bit =
| Zero
| One
type Signal = seq<Bit>
let Nand a b =
match a, b with
| Zero, Zero -> One
| Zero, One -> One
| One, Zero -> One
| One, One -> Zero
let Not input =
Nand input input
let And a b =
Not (Nand a b)
let Or a b =
Nand (Not a) (Not b)
let private liftToSignal1 op (signal: Signal) : Signal =
Seq.map op signal
let private liftToSignal2 op (signalA: Signal) (signalB: Signal) : Signal =
Seq.map2 op signalA signalB
let Not' = liftToSignal1 Not
let And' = liftToSignal2 And
let Or' = liftToSignal2 Or
let rec dff data clock : Signal =
seq {
yield Zero
yield! Or' (And' data clock)
(And' (dff data clock) (Not' clock))
}
This is an issue with structural vs. referential equality.
In F# seq { 'a' } = seq { 'a' } // false but [ 'a' ] = [ 'a' ] // true due to seq being IEnumerable and not supporting structural equality (or comparison).
Lists (and other F# container-like types) are much more 'intelligent', i.e. they support structural equality / comparison if the contained objects support it:
[ {| foo = StringComparison.Ordinal; bar = Some(1.23) |} ] =
[ {| foo = StringComparison.Ordinal; bar = Some(1.23) |} ] // true
but don't, if they contain anything that doesn't:
[ box(fun() -> 3) ] = [ box(fun() -> 3) ] // false
So, to make the test work, add a List.ofSeq:
dff Seq.empty Seq.empty |> List.ofSeq |> should equal [ Zero ]
I have a binary tree represented with nested lists:
[[[[], []], [[], []]], [[], [], []]]
And I want to write a function which removes the leafs (the empty lists) from it with recursion.
I tried with this but it doesn't even run. Could someone help me how to start?
def removeLeaf(tree):
for i in tree:
if type(tree[i]) is list:
return removeLeaf(tree[i])
elif tree[i] == []:
tree.pop(i)
return removeLeaf(tree)
input:
[[[[], []], [[], []]], [[], [], []]]
output:
[[[], []], []]
You shouldn't call resursion in the first part of if, because you are removing the empty list that is a leaf. Also the for sentence must be changed.
Here's the code:
def removeLeafs(tree):
for i in range(0,len(tree)-1):
if len(tree[i]) == 0:
tree.pop(i)
else
removeLeafs(tree[i])
I know there are other ways to avoid using Accumulators and the built in ++ will append one list to another list. However, if I build my own tail recursive append function with an accumulator, is there any way of getting around using lists:reverse() on one of the lists like the snippet below? Thanks
joinWithAccumulator2(X,Y) ->
joinWithAccumulator2(lists:reverse(X), [], Y).
joinWithAccumulator2( [], [], A ) ->
A;
joinWithAccumulator2( [X | Xs], [], A ) ->
joinWithAccumulator2( Xs, [], [ X | A] ).
The fastest way to build a list is to prepend elements using [H|T]. So the way you did it is efficient. If your purpose is to avoid to use the lib library, and in order to use the accumulator (see #juan.facorro comment) you can first reverse the first list in the accumulator, then prepend it to the second list:
joinWithAccumulator2(LX, LY) ->
joinWithAccumulator2(LX, LY, []).
% first step reverse LX in LA
joinWithAccumulator2( [X | Xs], LY, LA ) ->
joinWithAccumulator2( Xs, LY, [X | LA] );
% second step, when LX is empty, prepend LA to LY (list accumulator2)
joinWithAccumulator2( [], LA2, [A | As] ) ->
joinWithAccumulator2( [], [A | LA2], As );
% operation done
joinWithAccumulator2( [], A, [] ) ->
A.
I have finally found an excellent entry point into functional programming with elm, and boy, do I like it, yet I still lack some probably fundamental elegance concerning a few concepts.
I often find myself writing code similar to the one below, which seems to be doing what it should, but if someone more experienced could suggest a more compact and direct approach, I am sure that could give some valuable insights into this so(u)rcery.
What I imagine this could boil down to, is something like the following
(<-> is a vector subtraction operator):
edgeDirections : List Vector -> List Vector
edgeDirections corners = List.map2 (\p v -> p <-> v) corners (shiftr 1 corners)
but I don't really have a satisfying approach to a method that would do a shiftr.
But the rules of stackoverflow demand it, here is what I tried. I wrote an ugly example of a possible usage for shiftr (I absolutely dislike the Debug.crash and I am not happy about the Maybe):
Given a list of vectors (the corner points of a polygon), calculate the directional vectors by calculating the difference of each corner-vector to its previous one, starting with the diff between the first and the last entry in the list.
[v1,v2,v3] -> [v1-v3,v2-v1,v3-v2]
Here goes:
edgeDir : Vector -> ( Maybe Vector, List Vector ) -> ( Maybe Vector, List Vector )
edgeDir p ( v, list ) =
case v of
Nothing ->
Debug.crash ("nono")
Just vector ->
( Just p, list ++ [ p <-> vector ] )
edgeDirections : List Vector -> List Vector
edgeDirections corners =
let
last =
List.head <| List.reverse corners
in
snd <| List.foldl edgeDir ( last, [] ) corners
main =
show <| edgeDirections [ Vector -1 0, Vector 0 1, Vector 1 0 ]
I appreciate any insight into how this result could be achieved in a more direct manner, maybe using existing language constructs I am not aware of yet, or any pointers on how to lessen the pain with Maybe. The latter may Just not be possible, but I am certain that the former will a) blow me away and b) make me scratch my head a couple times :)
Thank you, and many thanks for this felicitous language!
If Elm had built-in init and last functions, this could be cleaner.
You can get away from all those Maybes by doing some pattern matching. Here's my attempt using just pattern matching and an accumulator.
import List exposing (map2, append, reverse)
shiftr list =
let shiftr' acc rest =
case rest of
[] -> []
[x] -> x :: reverse acc
(x::xs) -> shiftr' (x::acc) xs
in shiftr' [] list
edgeDirections vectors =
map2 (<->) vectors <| shiftr vectors
Notice also the shortened writing of the mapping function of (<->), which is equivalent to (\p v -> p <-> v).
Suppose Elm did have an init and last function - let's just define those quickly here:
init list =
case list of
[] -> Nothing
[_] -> Just []
(x::xs) -> Maybe.map ((::) x) <| init xs
last list =
case list of
[] -> Nothing
[x] -> Just x
(_::xs) -> last xs
Then your shiftr function could be shortened to something like:
shiftr list =
case (init list, last list) of
(Just i, Just l) -> l :: i
_ -> list
Just after I "hung up", I came up with this, but I am sure this can still be greatly improved upon, if it's even correct (and it only works for n=1)
shiftr : List a -> List a
shiftr list =
let
rev =
List.reverse list
in
case List.head rev of
Nothing ->
list
Just t ->
[ t ] ++ (List.reverse <| List.drop 1 rev)
main =
show (shiftr [ 1, 2, 3, 4 ] |> shiftr)
I'm trying to write some code in a functional paradigm for practice. There is one case I'm having some problems wrapping my head around. I am trying to create an array of 5 unique integers from 1, 100. I have been able to solve this without using functional programming:
let uniqueArray = [];
while (uniqueArray.length< 5) {
const newNumber = getRandom1to100();
if (uniqueArray.indexOf(newNumber) < 0) {
uniqueArray.push(newNumber)
}
}
I have access to lodash so I can use that. I was thinking along the lines of:
const uniqueArray = [
getRandom1to100(),
getRandom1to100(),
getRandom1to100(),
getRandom1to100(),
getRandom1to100()
].map((currentVal, index, array) => {
return array.indexOf(currentVal) > -1 ? getRandom1to100 : currentVal;
});
But this obviously wouldn't work because it will always return true because the index is going to be in the array (with more work I could remove that defect) but more importantly it doesn't check for a second time that all values are unique. However, I'm not quite sure how to functionaly mimic a while loop.
Here's an example in OCaml, the key point is that you use accumulators and recursion.
let make () =
Random.self_init ();
let rec make_list prev current max accum =
let number = Random.int 100 in
if current = max then accum
else begin
if number <> prev
then (number + prev) :: make_list number (current + 1) max accum
else accum
end
in
make_list 0 0 5 [] |> Array.of_list
This won't guarantee that the array will be unique, since its only checking by the previous. You could fix that by hiding a hashtable in the closure between make and make_list and doing a constant time lookup.
Here is a stream-based Python approach.
Python's version of a lazy stream is a generator. They can be produced in various ways, including by something which looks like a function definition but uses the key word yield rather than return. For example:
import random
def randNums(a,b):
while True:
yield random.randint(a,b)
Normally generators are used in for-loops but this last generator has an infinite loop hence would hang if you try to iterate over it. Instead, you can use the built-in function next() to get the next item in the string. It is convenient to write a function which works something like Haskell's take:
def take(n,stream):
items = []
for i in range(n):
try:
items.append(next(stream))
except StopIteration:
return items
return items
In Python StopIteration is raised when a generator is exhausted. If this happens before n items, this code just returns however much has been generated, so perhaps I should call it takeAtMost. If you ditch the error-handling then it will crash if there are not enough items -- which maybe you want. In any event, this is used like:
>>> s = randNums(1,10)
>>> take(5,s)
[6, 6, 8, 7, 2]
of course, this allows for repeats.
To make things unique (and to do so in a functional way) we can write a function which takes a stream as input and returns a stream consisting of unique items as output:
def unique(stream):
def f(s):
items = set()
while True:
try:
x = next(s)
if not x in items:
items.add(x)
yield x
except StopIteration:
raise StopIteration
return f(stream)
this creates an stream in a closure that contains a set which can keep track of items that have been seen, only yielding items which are unique. Here I am passing on any StopIteration exception. If the underlying generator has no more elements then there are no more unique elements. I am not 100% sure if I need to explicitly pass on the exception -- (it might happen automatically) but it seems clean to do so.
Used like this:
>>> take(5,unique(randNums(1,10)))
[7, 2, 5, 1, 6]
take(10,unique(randNums(1,10))) will yield a random permutation of 1-10. take(11,unique(randNums(1,10))) will never terminate.
This is a very good question. It's actually quite common. It's even sometimes asked as an interview question.
Here's my solution to generating 5 integers from 0 to 100.
let rec take lst n =
if n = 0 then []
else
match lst with
| [] -> []
| x :: xs -> x :: take xs (n-1)
let shuffle d =
let nd = List.map (fun c -> (Random.bits (), c)) d in
let sond = List.sort compare nd in
List.map snd sond
let rec range a b =
if a >= b then []
else a :: range (a+1) b;;
let _ =
print_endline
(String.concat "\t" ("5 random integers:" :: List.map string_of_int (take (shuffle (range 0 101)) 5)))
How's this:
const addUnique = (ar) => {
const el = getRandom1to100();
return ar.includes(el) ? ar : ar.concat([el])
}
const uniqueArray = (numberOfElements, baseArray) => {
if (numberOfElements < baseArray.length) throw 'invalid input'
return baseArray.length === numberOfElements ? baseArray : uniqueArray(numberOfElements, addUnique(baseArray))
}
const myArray = uniqueArray(5, [])