Pointers and references: Difference between revisions
Content added Content deleted
Thundergnat (talk | contribs) m (syntax highlighting fixup automation) |
|||
Line 939: | Line 939: | ||
Java is call-by-value. When passing arguments, you are either passing primitives by value or references by value. There is no such thing as "passing an object" as objects are not values in the language. As noted above, if the object that the reference is pointing to is mutable, then it is possible to modify that object's state through the reference. Then if the calling function has a reference to the same object, they will see that modification through the reference. So if you want to reflect changes in an argument back to the caller, one thing that you can do is wrap the argument as a field in an object, then modify the object through the reference. |
Java is call-by-value. When passing arguments, you are either passing primitives by value or references by value. There is no such thing as "passing an object" as objects are not values in the language. As noted above, if the object that the reference is pointing to is mutable, then it is possible to modify that object's state through the reference. Then if the calling function has a reference to the same object, they will see that modification through the reference. So if you want to reflect changes in an argument back to the caller, one thing that you can do is wrap the argument as a field in an object, then modify the object through the reference. |
||
=={{header|jq}}== |
|||
{{works with|jq}} |
|||
'''Also works with gojq, the Go implementation of jq''' |
|||
'''Also works with fq, a Go implementation of a large subset of jq''' |
|||
In the context of JSON, "JSON Pointer" usually refers to RFC 6901, |
|||
which defines a string format for accessing values from a JSON document |
|||
in an analogous manner as XPath defines a mechanism for accessing values from an XML document. |
|||
jq has no built-in support for JSON Pointer as it already provides an analogous mechanism |
|||
based on paths expressed as arrays. Specifically, a JSON array of strings and integers can be used to specify |
|||
a path, $p, and jq provides a function `getpath($p)` for accessing the value at the given path, $p. |
|||
In this entry, we will use the term "JSON pointer" to refer to either a JSON Pointer string, or a jq array path. |
|||
Neither JSON nor jq provides a mechanism for handling embedded JSON pointers, but a common convention |
|||
is to use a JSON object with a key named "$ref" as a reference. We will adopt this convention here, |
|||
as illustrated by the following JSON document: |
|||
<pre> |
|||
[ |
|||
{ |
|||
"name": "John", |
|||
"birthplace": "London" |
|||
}, |
|||
{ |
|||
"name": "Jim", |
|||
"birthplace": "Paris", |
|||
"father": { |
|||
"$ref": "/0" |
|||
} |
|||
} |
|||
] |
|||
</pre> |
|||
In the following, we extend jq's support for array paths to JSON pointers, and |
|||
add functionality for dereferencing "$ref" values, whether expressed as |
|||
array paths or JSON Pointer values. |
|||
Thus we will be able to write expressions such as: |
|||
<pre> |
|||
deref([1, "father"]) |
|||
deref( "/1/father" ) |
|||
</pre> |
|||
to retrieve the details concerning Jim's father. |
|||
We shall also ensure that deref can be used with jq's native query capabilities: |
|||
<pre> |
|||
deref( .[1]["father"] ) |
|||
deref( .[1] | .father ) |
|||
</pre> |
|||
'''Library''' |
|||
<syntaxhighlight lang=jq> |
|||
# Convert a jq array path to a JSON Pointer |
|||
def jsonpointer: |
|||
def encode: gsub("~"; "~0") | gsub("/"; "~1"); |
|||
reduce .[] as $x |
|||
(""; |
|||
if ($x|type) == "string" then "\(.)/\($x|encode)" |
|||
else . + "/\($x)" end ); |
|||
# Is the input syntactically a jq array path? |
|||
def isarraypath: |
|||
type == "array" and |
|||
all(.[]; type == "string" or (type == "number" and floor == .)); |
|||
# like getpath() but for jsonpointer pointers |
|||
def getjsonpointer($pointer): |
|||
# first decode ~1, then ~0 |
|||
($pointer | split("/") | .[1:] |
|||
| map(gsub("~1"; "/") | gsub("~0"; "~") | if test("^[0-9]+$") then tonumber else . end)) as $jqpath |
|||
| getpath($jqpath); |
|||
# like getpath() but allow $p to be a jsonpointer or an array |
|||
def getpointer($p): |
|||
if ($p|type) == "string" then getjsonpointer($p) |
|||
elif ($p|isarraypath) then getpath($p) |
|||
else $p |
|||
end; |
|||
# dereference $pointer, but not recursively. |
|||
# $pointer can be a jsonpointer pointer, or a jq array path, |
|||
# but one can also call deref(query) where `query` is a jq query yielding a $ref object. |
|||
def deref($pointer): |
|||
def resolve($x): |
|||
. as $in |
|||
| if ($x | type) == "object" |
|||
then $x["$ref"] as $ref |
|||
| if $ref then getpointer($ref) |
|||
else $x |
|||
end |
|||
else $x |
|||
end; |
|||
if ($pointer|type) == "string" |
|||
then resolve(getpointer($pointer)) |
|||
elif ($pointer|isarraypath) |
|||
then resolve(getpath($pointer)) |
|||
else resolve($pointer) |
|||
end; |
|||
</syntaxhighlight> |
|||
'''Examples''' |
|||
These examples correspond to the John/Jim JSON document shown above. |
|||
In each case, the result would be "John". |
|||
<pre> |
|||
getpointer("/0/name") # JSON Pointer |
|||
getpointer([0, "name"] ) # array path |
|||
deref("/1/father").name # JSON Pointer |
|||
deref([1,"father"] ).name # array path |
|||
deref(.[1]["father"] ).name # jq query |
|||
deref(.[1] | .father).name # jq query |
|||
deref(.[] | select(.name == "Jim").father ).name # jq query |
|||
</pre> |
|||
=={{header|Julia}}== |
=={{header|Julia}}== |