C# C中的自生
试着围绕perl的Autovivification进行思考,根据它听起来的样子,它的工作原理似乎类似于C中的dynamics,因为动态对象直到运行时才被分配类型,或者,我完全不在这里。如果是这样的话,有没有一个类似的想法,我可以在C语言中搭桥,这是有意义的? 编辑 好吧,看来我走远了。作为问题的第二部分,在C中有什么概念上的可比性吗?说得清楚一点,我在寻找一个C语言中的概念,它可以与自动生命化相媲美。不必完全相同,但在概念上足够接近,才能有意义。正如我所说的,我绝不是任何一个黑客或Python黑客,在任何想象的范围内,我都熟悉C语言,C,C++,C,java,JavaScript。我在考虑C的动态性,但现在我在考虑基于此处信息的延迟加载,如果这有帮助的话……Uri Guttman的可能会有一些用处 基本上,这是迄今为止未接触过的骨料和骨料成员首次使用时恢复生命的能力 例如,我可以这样做:C# C中的自生,c#,perl,dynamic,.net-4.0,autovivification,C#,Perl,Dynamic,.net 4.0,Autovivification,试着围绕perl的Autovivification进行思考,根据它听起来的样子,它的工作原理似乎类似于C中的dynamics,因为动态对象直到运行时才被分配类型,或者,我完全不在这里。如果是这样的话,有没有一个类似的想法,我可以在C语言中搭桥,这是有意义的? 编辑 好吧,看来我走远了。作为问题的第二部分,在C中有什么概念上的可比性吗?说得清楚一点,我在寻找一个C语言中的概念,它可以与自动生命化相媲美。不必完全相同,但在概念上足够接近,才能有意义。正如我所说的,我绝不是任何一个黑客或Python黑
#!/usr/bin/perl
use strict; use warnings;
use Data::Dumper;
my @dummy;
push @{ $dummy[0] }, split ' ', 'this that and the other';
push @{ $dummy[1] }, { qw(a b c d) };
print Dumper \@dummy;
取消引用之前,$dummy[0]和$dummy[1]都不存在
现在,如果你愿意放弃严格的要求,你也可以这样做:
use Data::Dumper;
@$x = qw(a b c d);
print Dumper $x;
因此,未定义变量$x将成为数组引用,因为它正被取消引用。您可以通过创建IDictionary来实现类似自动验证的行为,例如,当出现[]到未设置键时,返回并存储新IDictionary的IDictionary以递归方式返回并存储相同类型的IDictionary。这种方法在Ruby中获得了巨大的成功——然而,它在静态类型语言中并没有那么有用,因为无法干净地获取叶值——至少在大多数现有契约(如IDictionary)的上下文中是如此
随着dynamic的出现,这在C中可能很正常,但我不知道。我不能说C,但用外行的话来说,Perl的自动激活是在需要时用未定义的值创建容器对象的过程 尽管大多数Perl都是动态的,但Perl的去引用语法在编译时明确地指定了引用的类型。这允许解释器在定义变量之前知道它需要从变量中得到什么
my $var; # undefined
# to autovivify to an array:
@$var = 1..5; # @ here implies ARRAY
$$var[4] = 5; # square brackets imply ARRAY
$#$var; # $# implies ARRAY (returns the last index number)
# to autovivify to a hash:
%$var = (a => 1); # % implies HASH
$$var{asdf} = 5; # curly braces imply HASH
这个列表可能更长,但应该会给你一个想法
所以基本上,当你有这样一条线:
my $var;
$var->[1]{x}[3]{asdf}
Perl在->的右侧看到了方括号。这意味着发票$var必须是数组引用。由于invocant是未定义的,Perl创建一个新数组并将其引用安装到$var中。然后,每次后续的取消引用都会重复相同的过程
因此,上面这一行实际上意味着:
(((($var //= [])->[1] //= {})->{x} //= [])->[3] //= {})->{asdf};
因此,基本上需要两件事,一是创建一个对象的能力,该对象支持使用数组和哈希下标或等效项进行索引,二是一种机制,使一个对象可以在内存中用另一个对象替换自己,或将自己锁定到一个解释,然后在内部存储新对象
下面的伪代码可能是一个开始:
class autoviv {
private var content;
method array_subscript (idx) {
if (!content) {
content = new Array();
}
if (typeof content == Array) {
if (exists content[idx]) return content[idx];
return content[idx] = new autoviv();
} else {
throw error
}
}
method hash_subscript (idx) {
if (!content) {
content = new Hash();
}
if (typeof content == Hash) {
if (exists content{idx}) return content{idx};
return content{idx} = new autoviv();
} else {
throw error
}
}
// overload all other access to return undefined, so that the value
// still looks empty for code like:
//
// var auto = new autoviv();
// if (typeof auto[4] == autoviv) {should run}
// if (auto[4]) {should not run}
}
对于C语言中类似于字典的自动活跃行为的简单实现,类似这样的东西怎么样?显然,这并不像Perl那样以通用的方式处理它,但我相信它具有相同的效果
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
// The purpose of this class is to provide a dictionary with auto-vivification behaviour similar to Perl's
// Using dict[index] will succeed regardless of whether index exists in the dictionary or not.
// A default value can be set to be used as an initial value when the key doesn't exist in the dictionary
namespace XMLTest
{
class AutoDictionary<TKey,TValue> : Dictionary<TKey,TValue> {
Object DefaultValue ;
public AutoDictionary(Object DefaultValue) {
this.DefaultValue = DefaultValue;
}
public AutoDictionary() {
this.DefaultValue = null;
}
public new TValue this[TKey index] {
get {
try {
return base[index];
}
catch (KeyNotFoundException) {
base.Add(index, (TValue)DefaultValue);
return (TValue)DefaultValue ;
}
}
set {
try {
base[index] = value ;
}
catch (KeyNotFoundException) {
base.Add(index, value);
}
}
}
}
}
我建议使用扩展方法而不是继承 e、 g:
使用索引器和C4.0动力学
class Tree
{
private IDictionary<string, object> dict = new Dictionary<string, object>();
public dynamic this[string key]
{
get { return dict.ContainsKey(key) ? dict[key] : dict[key] = new Tree(); }
set { dict[key] = value; }
}
}
// Test:
var t = new Tree();
t["first"]["second"]["third"] = "text";
Console.WriteLine(t["first"]["second"]["third"]);
DynamicObject还可以用于实现不同的语法
using System;
using System.Collections.Generic;
using System.Dynamic;
class Tree : DynamicObject
{
private IDictionary<object, object> dict = new Dictionary<object, object>();
// for t.first.second.third syntax
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
var key = binder.Name;
if (dict.ContainsKey(key))
result = dict[key];
else
dict[key] = result = new Tree();
return true;
}
public override bool TrySetMember(SetMemberBinder binder, object value)
{
dict[binder.Name] = value;
return true;
}
// for t["first"]["second"]["third"] syntax
public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result)
{
var key = indexes[0];
if (dict.ContainsKey(key))
result = dict[key];
else
dict[key] = result = new Tree();
return true;
}
public override bool TrySetIndex(SetIndexBinder binder, object[] indexes, object value)
{
dict[indexes[0]] = value;
return true;
}
}
// Test:
dynamic t = new Tree();
t.first.second.third = "text";
Console.WriteLine(t.first.second.third);
// or,
dynamic t = new Tree();
t["first"]["second"]["third"] = "text";
Console.WriteLine(t["first"]["second"]["third"]);
完全关闭。看,是的,我去过那里,但是我对Perl的一些更深奥的部分不是非常熟练,在python+1中也不是那么流利,因为我告诉我我完全不喜欢lol。必须从某个地方开始……Autovification是指在引用数据结构值时隐式创建它们。这与对象是否是动态无关,它描述了解释器如何决定在Perl中调用对象的对象方法在这个意义上是动态的。我认为pst的反应是正确的,关于C中的自动生命可能是什么样子。@mob:更具体地说:动态这个术语通常不是指对象的创建,而是指对象的类型。没关系。这是一个实际使用的词:到目前为止,还没有出现任何问题。嗯,感觉很特别。这是对自动活体化的一个很好的解释,但它没有回答实际问题。@cjm=>用伪代码更新,以用另一种语言实现自动活体化。仅限getter,setters的实现由读者决定。++,如果可以的话,我会+2,例如“如果没有自动激活,则自动激活”。Thx+1这肯定与我所要求的更接近。因此,是的,在C语言中可以潜在地进行自动激活,而延迟加载实际上是一个相关的概念。谢谢你回答我的问题谢谢 对于您的直接实现来说,已经有很多了。如果它不存在,添加它。
class Tree
{
private IDictionary<string, object> dict = new Dictionary<string, object>();
public dynamic this[string key]
{
get { return dict.ContainsKey(key) ? dict[key] : dict[key] = new Tree(); }
set { dict[key] = value; }
}
}
// Test:
var t = new Tree();
t["first"]["second"]["third"] = "text";
Console.WriteLine(t["first"]["second"]["third"]);
using System;
using System.Collections.Generic;
using System.Dynamic;
class Tree : DynamicObject
{
private IDictionary<object, object> dict = new Dictionary<object, object>();
// for t.first.second.third syntax
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
var key = binder.Name;
if (dict.ContainsKey(key))
result = dict[key];
else
dict[key] = result = new Tree();
return true;
}
public override bool TrySetMember(SetMemberBinder binder, object value)
{
dict[binder.Name] = value;
return true;
}
// for t["first"]["second"]["third"] syntax
public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result)
{
var key = indexes[0];
if (dict.ContainsKey(key))
result = dict[key];
else
dict[key] = result = new Tree();
return true;
}
public override bool TrySetIndex(SetIndexBinder binder, object[] indexes, object value)
{
dict[indexes[0]] = value;
return true;
}
}
// Test:
dynamic t = new Tree();
t.first.second.third = "text";
Console.WriteLine(t.first.second.third);
// or,
dynamic t = new Tree();
t["first"]["second"]["third"] = "text";
Console.WriteLine(t["first"]["second"]["third"]);