So im trying to execute this simple function:
declare function local:decodeBase64() as element(){
<root-element>
{
let $codepointsString := "77 97 110"
let $codepoints := fn:replace( $codepointsString,' ',', ')
let $x := fn:codepoints-to-string(xs:integer($codepoints))
return
$x
}
</root-element>
};
but i'm getting a error that i think it's because of xs:integer
however i can execute this code with the integer hardcoded
let $x := codepoints-to-string((77, 97, 110))
I noticed that i can run the code if i declare $codepoints as xs:integer* but i dont't know get a codePoint inside an element and use as xs:integer* to call codepoints-to-string function.
error:
http://www.w3.org/2005/xqt-errors}FORG0001: "77 97 110": invalid value for cast/constructor: {http://www.w3.org/2001/XMLSchema}integer: error: decimal: Invalid decimal value: unexpected char '32'
The original string needs to be split to multiple codepoint strings. The resulting strings can then be converted to integers:
let $codepointsString := "77 97 110"
let $codepoints := (
for $string in fn:tokenize($codepointsString, " ")
return xs:integer($string)
)
return fn:codepoints-to-string($codepoints)
let $jsonobject :=
{
"a": "val1 as value1",
"b": "val2 as value2, val3 as value3"
}
let $jsonarray :=
{
"a": "val1",
"b": [
"a1",
"a"
]
}
how are the above two different from each other? How can we convert the json array into json object using xquery?
Often, it is easiest to create a mutable map and array data structure and then convert to an immutable JSON object-node() or array-node(), as in:
let $jsonobject := xdmp:to-json(
map:entry("a", "val1 as value1")
=>map:with("b", "val2 as value2, val3 as value3")
)
let $jsonarray := xdmp:to-json(
map:entry("a", "val1")
=>map:with("b", json:to-array(("a1", "a")))
)
In most cases, immutable JSON nodes are needed only when inserting into the database. If the mutable map and array structure is sufficient, just omit the call to xdmp:to-json().
Hoping that helps,
According to the official Oracle documentation, the HashMap.getOrDefault(Object Key, V defaultValue) function can take two arguments, but the compiler reported an error when I run the following program.
fun main(args: Array<String>) {
val numbersMap = mapOf(
"one" to 1,
"two" to 2,
"three" to 3,
"four" to 4,
"five" to 5
)
println(numbersMap.get("one"))
println(numbersMap["one"])
println(numbersMap.getOrDefault("four", 10))
println(numbersMap["five"])
}
C:\Users\forestfh\Documents\KotlinProjects>kotlinc GetOrDefault.kt
GetOrDefault.kt:11:24: error: unresolved reference. None of the following candid
ates is applicable because of receiver type mismatch:
public inline fun <R, T : String> Result<String>.getOrDefault(defaultValue: Stri
ng): String defined in kotlin
println(numbersMap.getOrDefault("four", 10))
You can use getOrElse() extension function to retrieve either a stored value or default value:
println(numbersMap.getOrElse("four") { 10 })
I am reletively new to functional programming, to be honest about 2 days. I am trying to print out values from a Dict Int Int, but I can't seem to figure out how to pass this Dict Int Int to a function.
The error I am receiving is below.
The 1st argument to map is not what I expect:
32| div [] (Dict.map toLiDict dict)
^^^^^^^^ This toLiDict value is a:
Dict Int Int -> Html msg
But map needs the 1st argument to be:
Dict Int Int -> b
The function toHtmlDict and toLiDict is the one's causing me this issue, they are currently commented out below. Also I am calling this from the view, div [] [ toHtmlDict model.uniqueValues ], I have this commented out as well.
Here is what I am currently working with; I posted the whole code as it would be easier if you should need anything else.
Here's a link on Ellie here that can be ran.
module Main exposing (main)
import Browser
import Dict exposing (Dict)
import Html.Attributes
import Html exposing (Html, button, div, text, strong, p, li, ul)
import Html.Events exposing (onClick)
type alias Model =
{ currentNumber : Int, clicks : Int, outputList : List(String), uniqueValues : Dict Int Int }
--{ currentNumber : Int, clicks : Int, history : String, outputList : List(String) }
initialModel : Model
initialModel =
{ currentNumber = 0, clicks = 0, outputList = [""], uniqueValues = Dict.fromList [(1,1)] } --Dict.empty should be default here...
--{ currentNumber = 0, clicks = 0, history = "Current outputs ...", outputList = ["Current outputs ...", " "] }
-- applies a new div for each element in the list
toHtmlList : List String -> Html msg
toHtmlList strings =
div [] (List.map toLi strings)
-- creates a div along with the text to be shown
toLi : String -> Html msg
toLi s =
div [] [ text s ]
-- --applies a new div for each element in the dictionary
-- toHtmlDict : Dict Int Int -> Html msg
-- toHtmlDict dict =
-- div [] (Dict.map toLiDict dict)
-- -- creates a div along with the text to be shown
-- toLiDict : Dict Int Int -> Html msg
-- toLiDict k =
-- div [] [ text "What here?" ]
type Msg
= Increment
| Decrement
update : Msg -> Model -> Model
update msg model =
case msg of
-- Note: when assigning the model.currentNumber and then concatenating the value, it will not be updated...
Increment ->
{ model | currentNumber = model.currentNumber + 1, clicks = model.clicks + 1, outputList = model.outputList ++ [addToPage (oddOrEven(model.currentNumber + 1)) (model.currentNumber + 1)], uniqueValues = model.uniqueValues }
--{ model | currentNumber = model.currentNumber + 1, clicks = model.clicks + 1, history = model.history ++ addToPage (oddOrEven(model.currentNumber + 1)) (model.currentNumber + 1), outputList = model.outputList ++ [addToPage (oddOrEven(model.currentNumber + 1)) (model.currentNumber + 1)] }
Decrement ->
{ model | currentNumber = model.currentNumber - 1, clicks = model.clicks + 1, outputList = model.outputList ++ [addToPage (oddOrEven(model.currentNumber - 1)) (model.currentNumber - 1)]}
--{ model | currentNumber = model.currentNumber - 1, clicks = model.clicks + 1, history = model.history ++ addToPage (oddOrEven(model.currentNumber - 1)) (model.currentNumber - 1), outputList = model.outputList ++ [addToPage (oddOrEven(model.currentNumber - 1)) (model.currentNumber - 1)]}
view : Model -> Html Msg
view model =
Html.div []
[ button [ onClick Increment ] [ strong [Html.Attributes.style "color" "black"] [ text "+1" ]]
, button [ onClick Decrement ] [ strong [Html.Attributes.style "color" "red"] [ text "-1" ]]
, p [] []
--, div [] [ text <| "The current number is: ", strong [Html.Attributes.style "color" "red"] [ text <| String.fromInt model.currentNumber ], text " and it's ", text (oddOrEven model.currentNumber) ]
, div [] [ text <| "The current number is: ", strong [Html.Attributes.style "color" <| evenOddColor model.currentNumber] [ text <| String.fromInt model.currentNumber ], text " and it's ", strong [Html.Attributes.style "color" <| evenOddColor model.currentNumber ] [ text <| oddOrEven model.currentNumber ] ]
, div [] [ text "Total clicks: ", strong [Html.Attributes.style "color" "red"] [ text <| String.fromInt model.clicks ]]
, p [] []
, div [] [ strong [Html.Attributes.style "color" "Blue"] [ text "Unique values ..." ]]
, p [] []
--, div [] [ toHtmlDict model.uniqueValues ]
--, div [] [ text <| "The current number is: " ++ String.fromInt model.currentNumber ++ " and it's " ++ oddOrEven model.currentNumber ]
--, div [] [ text "Total clicks: ", strong [Html.Attributes.style "color" "red"] [ text <| String.fromInt model.clicks ]]
--, p [] []
, div [] [ strong [Html.Attributes.style "color" "Blue"] [ text "History ..." ]]
, p [] []
--, div [] [ text <| model.history ] - TEMPORARY
, div [] [ toHtmlList model.outputList ]
]
-- appendToList string number =
-- "Number was " ++ String.fromInt number ++ " and it was " ++ string
addToPage string number =
"Number was " ++ String.fromInt number ++ " and it was " ++ string
-- determines if number is even or odd
oddOrEven number =
if modBy 2 number == 0 then
"even"
else
"odd"
-- call another function with param
evenOddColor number =
if oddOrEven(number) == "even" then
"green"
else
"red"
main : Program () Model Msg
main =
Browser.sandbox
{ init = initialModel
, view = view
, update = update
}
Dict.map is a function that will transform the values of a Dict and return another Dict with the new values. This is not what you want here, but lets try to grok its type anyway, because it's a useful learning experience.
Dict.map
A Dicts full type is Dick k v, meaning that the type variables correspond to the type of its keys and values respectively. Dict.map, according to the documentation, has the type (k -> a -> b) -> Dict k a -> Dict k b. As its first argument it takes a function of two arguments, k and a, and that returns a b. maps second argument is a Dict k a, and it returns a Dict k b.
We can see that the k is the same in both the input and return Dicts, which means its type will remain the same, but the type variable for the values is different, a in the input and b in the return Dict. And the function similarly takes a as one of its inputs, along with a k, and returns a b. So for each of the key-value pairs in the input Dict, the mapping function will be called with its key, 'k', and value 'a', and is expected to return a b value.
For a Dict Int Int as you have, both k and v are Ints. If we substitute these in the type of Dict.map we get (Int -> Int -> b) -> Dict Int Int -> Dict Int b. We don't know what b is yet since that will be determined by the function we pass it, but we can at least see that the function expects two Int arguments`.
Meanwhile, the function you give it, toLiDict, has the type Dict Int Int -> Html msg which takes one argument that isn't an Int. This is what the error message is clumsily trying to convey. We could rewrite toLiDict to conform to what Dict.map expects, as a function Int -> Int -> Html msg, but that would have Dict.map return a Dict Int (Html msg), which isn't what you want. So let's drop that.
In general, map functions conventionally transform the elements of a collection without changing the type of collection.
Dict.foldl
If you want instead is to transform the elements of a collection into something else entirely, and there isn't something more specific to use, a "fold" is usually the right tool. Dict provides foldl and foldr, which basically does the same thing but in different order, foldl iterates over the elements from the "left" and foldr from the "right". If the order doesn't matter, use foldl because it's more efficient.
The type signature of Dict.foldl is (k -> v -> b -> b) -> b -> Dict k v -> b. That is, the transformation function now takes three arguments, the key, k, value, v, and a b which we'll call the accumulator, and returns a b. foldl itself also takes an additional argument, again a b, which will be the initial b value passed to the transformation function. The third argument is the Dict, and the return value is again a b.
For each key-value pair in the input Dict, foldl will, just like map, call the transformation function with its key and value. But it also provides a b which initially is the b value passed to foldl itself, but for subsequent iterations will be the b value returned from the transformation function. In that way the "accumulator" accumulates the return value.
Let's rewrite your code to use Dict.foldl instead:
toHtmlDict : Dict Int Int -> Html msg
toHtmlDict dict =
div [] (Dict.foldl toLiDict [] dict)
toLiDict : Int -> Int -> List (Html msg) -> List (Html msg)
toLiDict k v acc =
div [] [ text "What here?" ] :: acc
Here, toHtmlDict remains largely the same, but uses Dict.foldl instead of Dict.map and provides it an initial value of an empty list, [].
toLiDict sees bigger changes. Its type has changed to Int -> Int -> List (Html msg) -> List (Html msg), mneaning it takes the arguments: The key and value, both of which are Ints, and the accumulator is a List (Html msg), as is the return value.
But the implementation has barely changed. Instead of just returning an element directly, it's appended to the accumulator with :: acc.
And that's all there is to it. The result of the fold is the accumulated list of Html elements, as expected. If you plop the above code into yours, it will work.
Dict.values and Dict.toList
Finally, I noted earlier that foldl is a good choice if there aren't more appropriate specialized function. And since the end result you want is a list, either Dict.values or Dict.toList, as #bdukes has suggested, probably are. These aren't as efficient as a fold, since you'll iterate trough the elements twice, once to convert to a list and then to map them, but this rarely matters in practice. Specialized functions are also more descriptive and documents your intent better, so use them if you can.
The definition of Dict.map is (k -> a -> b) -> Dict k a -> Dict k b. So it takes a function and a Dict and returns a new Dict. That mapping function takes the key and value, and returns a new value.
In your case, you're looking to return a List (Html Msg), rather than a Dict of anything. So, rather than using Dict.map, I would call Dict.values to get a List of the values, and then use List.map to transform those values into Html Msg. If you need both the key and value to generate the Html Msg, use Dict.toList instead, to get a List (k, v) (i.e. a List of tuples, where the tuple has the key and value).
toHtmlDict : Dict Int Int -> Html Msg
toHtmlDict dict =
div [] (List.map viewDictEntry (Dict.toList dict))
viewDictEntry : (Int, Int) -> Html Msg
viewDictEntry (key, value) =
li [] [ text (String.fromInt key), text " = ", text (String.fromInt value) ]
I have a strange issue with the following code :
var dict = ["KEY" : [1, 2]]
println(dict["KEY"]) // Output is "Optional([1, 2])"
println(dict["KEY"]!) // Output is "[1, 2]"
dict["KEY"]!.append(3) // Error : '(String, Array<Int>)' does not have a member named 'append'
dict["KEY"]! += 3 // Error : type 'DictionaryIndex<String, Array<Int>>' does not conform to protocol 'StringLiteralConvertible'
My goal is to transform the dict variable from ["KEY" : [1, 2]] to ["KEY" : [1, 2, 3]].
I have probably missed something but I don't see what.
Firstly, from apple docs:
Conversely, if you assign an array or a dictionary to a constant, that
array or dictionary is immutable, and its size and contents cannot be
changed.
I think if you assign an array as a value of key within dictionary it goes the same way.
In addition Swift collections are copied whenever they are assigned or passed as a parameter.
If you really want to change array in dict, I guess you may create new array with appended items for example and reassign the value of dict
var arrayInit = [1, 2]
var dict = ["KEY" : arrayInit]
//somewhere
var array = dict["KEY"]!
array.append(3)
dict["KEY"] = array;
println(dict["KEY"]!) // Output is "[1, 2]"
That will do it...
import Cocoa
import Foundation
var dict = ["KEY" : [1, 2]]
println(dict["KEY"]) // Output is "Optional([1, 2])"
println(dict["KEY"]!) // Output is "[1, 2]"
var array = dict["KEY"]!
array.append(3)
array += 3
dict["KEY"] = array