I am writing a presto query
transform_values(
string_int_map,
(k, v) -> IF(
some_string LIKE '%v%',
1,
0
)
)
the 'v' inside like expression is the variable from (k, v). How can I make it happen?
Related
I'm a beginner in functional programming but I'm famaliar with imperative programming. I'm having trouble translating a piece of cpp code involving updatating two objects at the same time (context is n-body simulation).
It's roughly like this in c++:
for (Particle &i: particles) {
for (Particle &j: particles) {
collide(i, j) // function that mutates particles i and j
}
}
I'm translating this to Ocaml, with immutable objects and immutable Lists. The difficult part is that I need to replace two objects at the same time. So far I have this:
List.map (fun i ->
List.map (fun j ->
let (new_i, new_j) = collide(i, j) in // function that returns new particles i, j
// how do i update particles with new i, j?
) particles
) particles
How do I replace both objects in the List at the same time?
The functional equivalent of the imperative code is just as simple as,
let nbody f xs =
List.map (fun x -> List.fold_left f x xs) xs
It is a bit more generic, as a I abstracted the collide function and made it a parameter. The function f takes two bodies and returns the state of the first body as affected by the second body. For example, we can implement the following symbolic collide function,
let symbolic x y = "f(" ^ x ^ "," ^ y ^ ")"
so that we can see the result and associativity of the the collide function application,
# nbody symbolic [
"x"; "y"; "z"
];;
- : string list =
["f(f(f(x,x),y),z)"; "f(f(f(y,x),y),z)"; "f(f(f(z,x),y),z)"]
So, the first element of the output list is the result of collision of x with x itself, then with y, then with z. The second element is the result of collision of y with x, and y, and z. And so on.
Obviously the body shall not collide with itself, but this could be easily fixed by either modifying the collide function or by filtering the input list to List.fold and removing the currently being computed element. This is left as an exercise.
List.map returns a new list. The function you supply to List.map may transform the elements from one type to another or just apply some operation on the same type.
For example, let's assume you start with a list of integer tuples
let int_tuples = [(1, 3); (4, 3); (8, 2)];;
and let's assume that your update function takes an integer tuple and doubles the integers:
let update (i, j) = (i * 2, j * 2) (* update maybe your collide function *)
If you now do:
let new_int_tuples = List.map update int_tuples
You'll get
(* [(2, 6); (8, 6); (16, 4)] *)
Hope this helps
I have a function
f : a -> b -> ( a, c )
and I need to apply f to a list of b, while a is accumulated and c is appended to a list, getting ( a, List c ). I think the signature of what I want to do is
(a -> b -> ( a, c )) -> a -> List b -> ( a, List c )
The real scenario here is that I have
getThing : Model -> Thing -> ( Model, Cmd Msg )
and need to run getThing on a list of Thing, passing the Model to each call to getThing and returning the model and all Cmds that are to be performed in a Platform.Cmd.batch.
I think this problem should be broken down into multiple parts, but I am not sure where to start. It feels like using a fold is appropriate for the Model, but I need a map for the Cmd part.
You just need to unpack the tuple returned by getThing in each iteration of the fold, then pack it back up with the command added to the accumulated list of commands as the accumulator.
mapThings : (a -> b -> ( a, c )) -> a -> List b -> ( a, List c )
mapThings getThing initialModel things =
List.foldl
(\thing ( model, cmds ) ->
let
( newModel, cmd ) =
getThing model thing
in
( newModel, cmd :: cmds )
)
( initialModel, [] )
things
The naming here is very specific to help mnemonics, but it can easily be generalized just by using more generic variable names.
If you don't mind pulling in another package, there's elm-community/list-extra List.Extra.mapAccuml and List.Extra.mapAccumr
https://package.elm-lang.org/packages/elm-community/list-extra/latest/List-Extra#mapAccuml
I am working through the Purescript By Example tutorial and I am having trouble getting types to line up using a fold left as such:
smallestFile' :: [Path] -> Maybe Path
smallestFile' (x : xs) = foldl(\acc i -> smallerFile(acc i) ) Just(x) xs // Error is on this line
smallerFile :: Maybe Path -> Path -> Maybe Path
smallerFile maybeA b = do
a <- maybeA
sa <- size a
sb <- size b
if sa > sb then return(b) else return(a)
The error I am receiving is on the fold left and is
Cannot unify Prim.Function u13116 with Data.Maybe.Maybe
I believe that the types line up, but I cannot make heads or tails of this error.
Also, is it possible to clean up the anonymous function syntax so that
foldl(\acc i -> smallerFile(acc i) ) Just(x) xs
becomes something like:
foldl smallerFile Just(x) xs
In PureScript, like Haskell, function application uses whitespace, and associates to the left, which means that f x y z parses as ((f x) y) z. You only need parentheses when terms need to be regrouped. It looks like you're trying to use parentheses for function application.
I suspect what you want to write is
foldl (\acc i -> smallerFile acc i) (Just x) xs
The argument to foldl is a function which takes two arguments acc and i and returns the application smallerFile acc i. This is equivalent to the double application (smallerFile acc) i. First we apply the argument acc, then the second argument i. The precedence rule for function application in the parser makes these equivalent.
Also, Just x needs to be parenthesized because what you wrote parses as
foldl (\acc i -> smallerFile (acc i)) Just x xs
which provides too many arguments to foldl.
Once you have the correct version, you can notice that \acc i -> smallerFile acc i is equivalent to \acc -> (\i -> (smallerFile acc) i). The inner function applies its argument i immediately, so we can simplify this to \acc -> smallerFile acc. Applying this simplification a second time, we get just smallerFile, so the code becomes:
foldl smallerFile (Just x) xs
so the only mistake in the end was the incorrect bracketing of Just x.
there is piece of ocaml which works correctly
type position = {symbol: string; holding: int; pprice : float; };;
type account = {name: string; max_ind_holding:float; pos:position list};;
let print_position pos = print_string "Holding: "; print_int pos.holding;
print_string ( " " ^ pos.symbol ^ "#" );
print_float pos.pprice;
print_newline( );;
let print_account acct = print_string ( "Account_ID " ^ acct.name );
print_newline( );
List.iter print_position acct.pos;;
(*MAIN PART OF CODE *)
let hashtbl_function db =
let hash_tbl_fold = Hashtbl.fold ( fun x y z -> ( ( y ) :: z ) ) db [] in
( fun x -> List.iter print_account x ) hash_tbl_fold (* THIS WORKS FINE *)
;;
But, if i want to change last like to do iteration of 'position list' in this function (not in print_account), i will got error :
let hashtbl_function db =
let hash_tbl_fold = Hashtbl.fold ( fun x y z -> ( ( y ) :: z ) ) db [] in
( fun x -> List.iter print_position x ) hash_tbl_fold.pos (* Why this doesn't work ???*)
;;
Error: This expression has type 'a list but is here used with type account
But hash_tbl_fold.pos is list of position, this is not account type. Right?
In print_account - acct.pos (to get 'a list) is work, but in hashtbl_function, hash_tbl_fold.pos -> not.
How it can be, that the same expression only works in one of the functions ?
How i can iterate 'position list' in hashtbl_function?
thanks in advance!
Well, I'm not sure what exactly you want to do but I can tell you why it doesn't work.
hashtbl_fold gives you a list of accounts (type account list) but then you are doing hashtbl_fold.pos; you cannot get a pos field of a list, hence the error.
In print_account, acct.pos works because acct is a single account; not a list of accounts.
What do you want to do? Print all positions of all accounts? Or just positions of a single (which?) account?
Your answer (this is not account, but account list type) help me to figure it out.
Now, i can use hash_tbl_fold.pos inside my hashtbl_function.
This works for me:
let hash_tbl_fold = Hashtbl.fold ( fun x y z -> ( ( y ) :: z ) ) db [] in
List.iter ( fun x -> List.iter print_position x.pos ) hash_tbl_fold
Tnx!
For an assignment, i have written the following code in recursion. It takes a list of a vector data type, and a vector and calculates to closeness of the two vectors. This method works fine, but i don't know how to do the recursive version.
let romulus_iter (x:vector list) (vec:vector) =
let vector_close_hash = Hashtbl.create 10 in
let prevkey = ref 10000.0 in (* Define previous key to be a large value since we intially want to set closefactor to prev key*)
if List.length x = 0 then
{a=0.;b=0.}
else
begin
Hashtbl.clear vector_close_hash;
for i = 0 to (List.length x)-1 do
let vecinquestion = {a=(List.nth x i).a;b=(List.nth x i).b} in
let closefactor = vec_close vecinquestion vec in
if (closefactor < !prevkey) then
begin
prevkey := closefactor;
Hashtbl.add vector_close_hash closefactor vecinquestion
end
done;
Hashtbl.find vector_close_hash !prevkey
end;;
The general recursive equivalent of
for i = 0 to (List.length x)-1 do
f (List.nth x i)
done
is this:
let rec loop = function
| x::xs -> f x; loop xs
| [] -> ()
Note that just like a for-loop, this function only returns unit, though you can define a similar recursive function that returns a meaningful value (and in fact that's what most do). You can also use List.iter, which is meant just for this situation where you're applying an impure function that doesn't return anything meaningful to each item in the list:
List.iter f x