2017-10-19 16 views
1

私はLodash(javascriptライブラリ)(https://lodash.com/docs/4.17.4#filter)のフィルタ関数をシミュレートする次のprocを書きました。サンプルセクションにある3.5の基本形式で呼び出すことができます。後者の3つの呼び出しオプションについては、-s(略記)を送るという要求を取り除きたいと思っています。そのためには、匿名のprocとlist/dict/stringを区別する必要があります。Tcl - list/dictと匿名プロキシの区別

string isを見てみましたが、文字列がprocではありません。ここでの研究ではhttp://wiki.tcl.tk/10166info completeをお勧めしますが、ほとんどの場合、パラメータの種類に関係なく、そのテストに合格します。

これを信頼できる方法を知っている人はいますか?私はそれを残したり、proc定義を変更することができますが、私はできるだけ真実にとどまるよう努めています。

例:

set users [list \ 
      [dict create user barney age 36 active true] \ 
      [dict create user fred age 40 active false] \ 
     ] 

1. set result [_filter [list 1 2 3 4] {x {return true}}] 
2. set result [_filter $users -s [dict create age 36 active true]] 
3. set result [_filter $users -s [list age 36]] 
4. set result [_filter $users -s "active"] 

PROCコード:

proc _filter {collection predicate args} { 

# They want to use shorthand syntax 
if {$predicate=="-s"} { 

    # They passed a list/dict 
    if {[_dictIs {*}$args]} { 
     set predicate {x { 
      upvar args args 
      set truthy 1 
      dict for {k v} {*}$args { 
       if {[dict get $x $k]!=$v} { 
        set truthy false 
        break 
       } 
      } 
      return $truthy 
     }} 

    # They passed just an individual string 
    } else { 
     set predicate {x { 
      upvar args args; 
      if {[dict get $x $args]} { 
       return true; 
      } 
      return false; 
     }} 
    } 
} 

# Start the result list and the index (which may not be used) 
set result {} 
set i -1 

# For each item in collection apply the iteratee. 
# Dynamically pass the correct parameters. 
set paramLen [llength [lindex $predicate 0]] 
foreach item $collection { 
    set param [list $item] 
    if {$paramLen>=2} {lappend param [incr i];} 
    if {$paramLen>=3} {lappend param $collection;} 
    if {[apply $predicate {*}$param]} { 
     lappend result $item 
    } 
} 
return $result 
} 

答えて

2

x {return true}文字列、リスト、辞書やラムダ項(匿名PROCの正しい名前)ですか?

真実は、すべてです。言及されたタイプのいずれかのメンバーであったということは正しいでしょう。ある種の魔法の中に隠すのではなく、あなたの意図をより正確かつ明示的に記述する必要があります。そのより高い精度は、-sのようなオプションを使用するか、別のメインコマンド名を使用することで実現できますが、それでもいずれかの方法が必要です。あなたは、あなたがしようとすることを正しく安全に行うことはできません。もう少し深さで


...

すべてのTcl値は文字列として有効です。

リストには構文が定義されており、文字列の適切なサブタイプです。

ディクショナリの構文は、偶数インデックスの要素がすべて互いに唯一である偶数個の要素を持つリストと同等の構文を持ちます。これは、内部的に実装されていますが、そのような詳細は無視されます。

ラムダ用語は、2つまたは3つの要素を持つリストです(3つ目の要素はコンテキスト名前空間の名前です。存在しない場合は、グローバル名前空間の既定値です)。リストの最初の要素も有効なリストでなければなりません。

2要素リストは、上記のすべての要件に一致します。 Tclの実際のタイプのロジックでは、同時にすべてです。値の特定のインスタンス化は、カバーの下で特定の実装表現を持つかもしれませんが、それは値の真の型を反映しない一時的なものです。

Tclのシステムは、他の多くの言語のシステムとは異なります。

+0

ラムダ用語がこれを持っていると言う人は賢明な方法を持っていたのですが、リスト/ dict /ストリングはそうではありません。私が見る唯一の潜在的な違いは、lambda = 2または3です。もし3ならば、私はラムダを仮定することができます。しかし、もしlen = 2ならば、私が考えることができるのは、最初のコンポーネント(args)を見て、それが1より大きいかどうか、もしそうなら、ラムダまたはスペースを持つdictキーでしょうか。最終的に、私は同じ結論に達しましたが、誰かがもっと賢いかどうかを見たいと思っていました... –

関連する問題