2016-04-11 10 views
3

Çalıştırılması gereken komutların bir dizesini [] yineleyen f # içinde bir özyinelemeli işlevim var, her komut bir sonraki işleve iletilecek bir harita oluşturmak için yeni bir komut çalıştırıyor.biçimlendirme Kompozit işlevi f #

Komutlar düzgün bir şekilde çalışıyor ancak büyük ve hantaldır, okumalıyım, bu kompozit fonksiyonları sipariş etmek/biçimlendirmek için daha iyi bir yol olduğuna inanıyorum. işe almak için görünmüyor.

benim için emirdir:

let rec iterateCommands (map:Map<int,string array>) commandPosition = 
    if commandPosition < commands.Length then 
     match splitCommand(commands.[0]).[0] with 
     |"comOne" -> 
      iterateCommands (map.Add(commandPosition,create(splitCommand commands.[commandPosition])))(commandPosition+1) 

i başarmış yakın işlevini girintileyerek ama bu dağınık şudur: f # Bu yeniden biçimlendirmek bile mümkündür

iterateCommands 
(map.Add 
    (commandPosition,create 
     (splitCommand commands.[commandPosition]) 
    ) 
) 
(commandPosition+1) 

mi? okudum ne ben mümkün inanın itibaren herhangi bir yardım büyük olacak

The command/variable types are: 
commandPosition - int 
commands - string[] 
splitCommand string -> string[] 
create string[] -> string[] 
map : Map<int,string[]> 

ve tabii map.add haritası takdir ediyorum -> Harita + x

+0

Lütfen oluşturmak istediğiniz işlevlerin tanımlarını veya en azından türlerini paylaşın. –

+0

Ben tüm fonksiyonları ve değişkenleri türleri dahil etmek için cevabımı düzenledim –

cevap

2

çağrıyı oluşturmak için biraz daha kolay olurdu: gibi bir şey yazmanızı sağlayacak

let rec iterateCommands commandPosition (map:Map<int,string array>) = 
    // ... 

:

splitCommand commands.[commandPosition] 
|> create 
|> (fun x -> commandPosition, x) 
|> map.Add 
|> iterateCommands (commandPosition + 1) 

Sâhi commandPosition görünür Kompozisyonda thrice bence, bu tüm ifadenin türü unit olduğu gerçeği gibi, bir tasarım kokusu olduğunu. Özellikle işlevsel görünmüyor, fakat bu işlevin tam olarak ne yapmaya çalıştığını tam olarak anlayamadığımdan, daha iyi bir tasarım öneremem.

Eğer argüman sırasını değiştiremezsiniz dolayısıyla iterateCommands kontrol ve yoksa, her zaman standart bir fonksiyonel programlama yarar fonksiyonu tanımlayabiliriz: Bu sağlar

let flip f x y = f y x 

karşı aşağıdaki yazmak için Orijinal sürümü iterateCommands:

splitCommand commands.[commandPosition] 
|> create 
|> (fun x -> commandPosition, x) 
|> map.Add 
|> (flip iterateCommands) (commandPosition + 1) 
+0

Teşekkür ederim bu tam olarak ne olduğumu oldu =) iterateCommands geçirilen bir harita üzerindeki işlevleri yürüten her komuttan geçer ve tüm komutlar bir metin dosyası tamamlandığında oluşturulur ve uygulama biter. IterateCommands işlevinin, işlev tamamlandıktan sonra uygulama çıkışları tamamlandığında bir birim türünden başka bir şeye gereksinim duyduğuna inanmadım. Şu anda işlev çağrısı, iterateCommands Map.empty 0 öğesinin iterateCommands 0 Map olması durumunda değiştirilmesini önerir. boş? –

+1

@Matthewkingston Sağ, eğer 'üst' işlevi ise, 'birim' mükemmel bir dönüş tipidir. Benim hatam. –

3

O ne olup bittiğini çıkarmak etmek zor Çok girişli büyük bir açıklamada. Bireysel ifadelere isimler verebilirdim, böylece bir okuyucu herhangi bir pozisyona atlayabilir ve bir hesaplamada kullanılan değerlerde neyin doğru olduğu hakkında kaba bir fikre sahip olabilir, örn.

let inCommands = splitCommand commands.[commandPosition] 
let map' = map.Add (commandPosition, inCommands) 
iterateCommands map' inCommands 

Burada ne yapıldığını bilmediğimden beri, isimler çok anlamlı değildir. İdeal olarak, hesaplamanın bireysel adımlarını anlamaya yardımcı olurlar. Eğer etrafında argümanlar değişirse