Is there an more straight forward way (and less error prone due to maintenance and amount of editing involved), to achieve the same as below, that is: 1) getting a subset of the elements of a record, given the names list of members of interest, 2) and updating a record from a subset record, using the names of the subset record?
val r = {a = 1, b = 2, c = 3, d = 4, e = 5}
val s = {b = #b r, c = #c r, d = #d r}
val r = {a = #a r, b = #b s, c = #c s, d = #d s, e = #e r}
What I expect, could look like this:
val r = {a = 1, b = 2, c = 3, d = 4, e = 5}
val s = #(b, c, d) r
val r = r / s
As Sebastian Paaske Tørhol said, one can extract part of a record this way:
val {b, c, d, ...} = r
Unfortunately, this does not bind the subset to a single name, as this, as an example, does not work:
val s = {b, c, d, ...} = r
No, there isn't. There once was a proposal for more extensive record operations (Functional record extension and row capture), as part of the short-lived successor ML effort. With that, you could have written, e.g.,
val r = {a = 1, b = 2, c = 3, d = 4, e = 5}
val {a, e, ... = s} = r
val t = {a = a+1, e = e-1, ... = s}
Unfortunately, nobody ever implemented it in a real compiler.
You can use pattern-matching to extract relevant parts of records:
Example:
val question = { title = "SML record subset and update",
author = "Hibou57",
tags = ["SML"] }
val { title = t, tags = ts, ... } = question
This binds title into t and tags into ts.
You can also simply omit the names, if you so desire:
val { title, tags, ... } = question
This binds the title to title and tags to tags.
As far as updating goes, Standard ML sadly doesn't have a nice way to update records without explicitly having to set every field.
Related
I would like to compare 5 lists regarding their length and return the longest list.
I don't have any idea...
Maybe something like this:
a = [1,1,1,1]
b = [1]
c = [1,1,1]
d = [1,1,1,1,1]
e = [1,1,1,1,1]
L = [a,b,c,d,e]
def compare(lists):
counter = count()
previous = lists[0]
group_index = next(counter)
for value in lists:
if len(value) >= len(previous):
...
The result should be 'e'.
below is py3
a = [1,1,1,1]
b = [1]
c = [1,1,1]
d = [1,1,1,1,1]
e = [1,1,1,1,2]
f = [1,1,1,1,1,2]
L = [a,f,b,c,d,e]
def compare(lists):
previous = lists[0]
for value in lists:
if len(value) >= len(previous):
previous=value
return previous
Rsss=compare(L)
print(Rsss)
print([ k for k,v in locals().items() if v == Rsss][0])
python 2 change items to iteritems
print() to print
For example, this is the list of strings.
a = 'abcdefg'
b = 'efghij'
c = 'ij234235'
d = 'def'
e = 'efg'
f = 'fg'
str_list = [a, b, c, d, e, f]
I expect that the result would be ['abcdefghij234235', 'defg']
The concatenation should be executed sequentially and the common strings are not fixed
How can I get the result?
Th solution using numpy.intersect1d and itertools.chain.from_iterable() functions:
import numpy as np, itertools
str_list = [list(a), list(b), list(c), list(d), list(e), list(f)]
result = []
for k,a in enumerate(str_list):
if len(result) == 0:
result.append((str_list[k],))
if k+1 == len(str_list): break
common = ''.join(np.intersect1d(str_list[k],str_list[k+1]))
if common and common[-1] == ''.join(str_list[k])[-1] and common[0] in ''.join(str_list[k+1])[0]:
result[-1] += (str_list[k+1][len(common):],)
else:
result.append((str_list[k+1],))
result = [''.join(list(itertools.chain.from_iterable(t))) for t in result]
print(result)
The output:
['abcdefghij234235', 'defg']
How much memory is shared between objects during an immutable record or object update in OCaml? For example, for the records in the code:
type foo = {
a : int;
b : int;
c : int}
let f1 = {a = 1; b=2; c=3}
let f2 = {f1 with c=4}
How much memory is shared between f1 and f2? Basically, do they share memory for a and b? Similarly, for the objects in the code:
type ('i, 'j) lens = { get : 'j; set : 'j -> 'i }
class bar = object
val a = 1
method a = {
get = a;
set = fun a' -> {< a = a' >}
}
val b = 2
method b = {
get = b;
set = fun b' -> {< b = b' >}
}
val c = 3
method c = {
get = c;
set = fun c' -> {< c = c' >}
}
end
let b1 = new bar
let b2 = b1#c.set 4
How much memory is shared between b1 and b2?
Basically, imagine a situation where the fields a, b, and c are really, really big. I'd like to do an immutable update, but I don't want to have to copy all of that memory if possible.
For records, there would be no shared memory between f1 and f2 since an int takes as much memory as a pointer. There would be shared memory if you had more complex objects instead of int.
For example in
type foo = {
a : int list;
b : int list;
c : int list;
}
let f1 = {a = [1; 1; 1]; b = [2; 2; 2]; c = [3]}
let f2 = {f1 with c = [4]}
the lists of 1s and 2s would be shared between the two records.
It is a general rule in Ocaml that simple types (int, char, bool, …) are copied but complex types ('a list, 'a array, …) are shared. This is why immutable data structures are good: you can easily share. But beware, data is shared even if it is mutable:
type foo = {x : int ref; y : int ref}
let a = {x=ref 0; y = ref 0}
let b = {a with y = ref 1}
let () = b.x := 2
then a.x equals 2.
I want to check if all values in a list add up to some value. So far, I have written the following:
list_sum([Head|Tail], Sum) :-
list_sum(Tail, Sum1),
Sum is Head + Sum1.
However, when I try list_sum([1,2,3,4], 10) Prolog returns false.
Could someone help me out? I don't know what I'm doing wrong.
Use clpfd!
:- use_module(library(clpfd)).
For calculating the sum of a list of integers simply use clpfd library predicate
sum/3:
?- sum([1,2,3,4], #=, S). % Q: What is 1+2+3+4?
S = 10. % A: Sum is 10
?- sum([1,2,3,4], #=, 10). % Q: Does 1+2+3+4 equal 10?
true. % A: yes, it does
?- sum([1,2,3,4], #=, 11). % Q: Does 1+2+3+4 equal 11?
false. % A: no, it doesn't
A use case showing the benefits of using clpfd instead of (is)/2, suggested by #CapelliC:
?- [A,B,C] ins 1..sup, sum([A,B,C,A], #=, 12), labeling([], [A,B,C]).
A = B, B = 1, C = 9
; A = 1, B = 2, C = 8
; A = 1, B = 3, C = 7
; A = 1, B = 4, C = 6
; A = 1, B = C, C = 5
; A = 1, B = 6, C = 4
; A = 1, B = 7, C = 3
; A = 1, B = 8, C = 2
; A = C, B = 9, C = 1
; A = 2, B = 1, C = 7
; A = B, B = 2, C = 6
; A = 2, B = 3, C = 5
; A = 2, B = C, C = 4
; A = 2, B = 5, C = 3
; A = C, B = 6, C = 2
; A = 2, B = 7, C = 1
; A = 3, B = 1, C = 5
; A = 3, B = 2, C = 4
; A = B, B = C, C = 3
; A = 3, B = 4, C = 2
; A = 3, B = 5, C = 1
; A = 4, B = 1, C = 3
; A = 4, B = C, C = 2
; A = 4, B = 3, C = 1
; A = 5, B = C, C = 1.
It seems to me that this is rather simple.
Try this:
list_sum([], 0).
list_sum([Head|Tail], Sum):-
list_sum(Tail, Sum1),
Sum is Head + Sum1.
E.g. I have list A = {a,b,c,d}
How can I get list B = A without {b} element in one command?
B = Delete[A, 3]
or
B = DeleteCases[A, c]
A = {a, b, c, d};
B = Cases[A, Except[b]]