ingydotnet / yaml-libyaml-pm

Perl Binding to libyaml
http://search.cpan.org/dist/YAML-LibYAML/
33 stars 37 forks source link

Special key `<<` not being honoured #86

Open Altreus opened 5 years ago

Altreus commented 5 years ago

The << key in a YAML hash means merge.

http://yaml.org/refcard.html

Special keys: '=' : Default "value" mapping key. '<<' : Merge keys from another mapping.

This does not happen.

Reproducible example

firstmapping: &MAPPING
  akey: a value
  another-key:
    astructure:
       - a list 1
       - a list 2

secondmapping:
  <<: *MAPPING
  a-third-key: gets merged
➜ perl -MYAML::XS=LoadFile -MData::Dump -e'dd LoadFile("yaml.yml")'

Expected output

do {
  my $a = {
    firstmapping  => {
                       "akey" => "a value",
                       "another-key" => { astructure => ["a list 1", "a list 2"] },
                     },
    secondmapping => {
                       "akey" => "a value",
                       "another-key" => 'fix',
                       "a-third-key" => "gets merged"
                     },
  };
  $a->{"secondmapping"}{"another-key"} = $a->{"firstmapping"}{"another-key"};
  $a;
}

Observe that the only way to faithfully reproduce this is to copy the keys from the first mapping (but referencing the original values would be fine). I have only referenced the one that was already a ref since this seems like the most likely behaviour.

(I believe the fix syntax is just Data::Dump's way of preparing a structure to be self-referent. I borrowed it from the actual output below.)

Actual output

do {
  my $a = {
    firstmapping  => {
                       "akey" => "a value",
                       "another-key" => { astructure => ["a list 1", "a list 2"] },
                     },
    secondmapping => { "<<" => 'fix', "a-third-key" => "gets merged" },
  };
  $a->{secondmapping}{"<<"} = $a->{firstmapping};
  $a;
}

Observe that what actually happens is << is just a ref to the original thing. This strategy works for all keys except <<, which needs to be handled specially.

perlpunk commented 5 years ago

Yes, this << key is called a merge key: https://yaml.org/type/merge.html It wasn't really made official, but I know that it is implemented in many other YAML processors. It would be possible to implement it in YAML::XS, but I would first like to get @ingydotnet's ok before I start doing any work. It won't be trivial to implement it, because a merge key has impact on the surrounding mapping, so it would be quite some work.

Meanwhile, if it's possible for you to use a module with a not yet stable API, you could try out YAML::PP::LibYAML which is a subclass of YAML::PP, and use the merge key feature like that: YAML::PP::Schema::Merge

Altreus commented 5 years ago

Thanks, I didn't know about this alternative module :) I'm sure it will be fine to use for those cases when I particularly need that behaviour :+1:

rabbiveesh commented 1 year ago

I see that this has been sitting around for a few years; is there any chance that an effort to do this will get revived?

perlpunk commented 1 year ago

I wouldn't expect anyone to work on this in the near future. I have many other tasks, and there is the mentioned YAML::PP::LibYAML alternative.