專題介紹 - Malleable VI 的用途與 Polymorphic VI 的差異

最近都在搞結案程式跟文件寫到快死掉了,還是換換氣來介紹一些新東西。
不對,拖這麼久,應該也不算新東西了。

有朋友再問:LabVIEW 2017出了一個新的功能叫做Malleable VI,請問那個是什麼?



直接說明這種VI有點距離,不如來想像一下一個新的應用場景:

假設再寫一個系統的時候,將某種資料建為陣列,例如Boolean,此時突然需要一個功能:「將陣列中的最後一個元素取出」,我想這個功能對大家應該都不難:




但很不幸的此時又需要相同的功能,但資料型態是浮點數的陣列,多半人會透過另存並且複製架構並且變更資料型態,就可以完成這個需求:




當然,有經驗的人此時會突然認知到擴展的可能性,於是就又做了一個新的資料型態:




同時透過建立Polymorphic VI來達成使用多資料類型VI的彈性:



相信許多人此時也會意識到,此方式固然好用,但萬一如果資料型態百百種,那麼這些各式各樣的subVI將因應而生,反而增加維護的困難度。這時候或許有些人採取的對策則是透過Variant來解決這個問題:



當然,使用Variant的問題不少,主要設計所顧慮到的會有兩處:產生coercion dot以及非定義型態轉換的問題。前者因為輸入是Array,故可能導致大量的記憶體管理問題,後者則是萬一轉回資料型態時出錯,如輸入的為TypeDef的資料型態,可能會導致後續應用上的異常。

這時候,就可以考慮使用Malleable VI。

Malleable VI其實在LabVIEW 2016的時候就有了。只是或許在測試實驗階段,官方並沒有將其納入公開資料中。一直等到了LabVIEW 2017的時候才把這些功能拖出來亮相。

那麼Malleable VI到底是要解決什麼問題?
簡單說:多種資料輸入的需求透過相同程式碼來處理。

例如上述的情境,其實內部的程式碼都一模一樣,只是資料型態不同。在原先的subVI設計中,因為指定了connector pane的資料型態,故其他資料型態並無法共用程式碼,唯一只能夠靠Variable來解決半套的問題。反過來說,如果能像Polymorphic VI般自動切換輸出入connector pane的資料型態,又能使用同一段程式碼,那就解決了大多數此類的問題。

那麼如何產生Malleable VI?一是透過New...中可以新增Malleable VI,另一則是在VI存檔時附檔名輸入.vim即可。

同樣的如何設定自動切換的connector pane,基本上都與一般的做法相同,唯一不同的是輸入的資料型態必須預設為Variant,無論是單純的Variant或是Array of Variant都可。此外輸出也必須是Variant,資料型態將會隨著輸入一併變更。例如下圖:




大家可以注意到這張圖的程式碼跟上面某張圖一樣,但差異在於Run Arrow是斷掉的。
不用擔心,Malleable VI本來就會是這樣,因為還需要設定其他的東西。
答案是必須把Malleable VI設定為Inline subVI into calling VI。



我想這樣的設計是為了讓系統在compile的時候直接判斷對應的資料型態,並且直接進行編譯,故無法讓subVI透過呼叫的方式執行,因為資料型態不定。

當設定完畢後,使用這個Malleable VI:




此時可以發現之前顧慮的coercion dot以及資料轉換都沒有了!就是這麼神奇。

Malleable VI與Polymorphic VI還是有些差異性:


Polymorphic VI
Malleable VI
彈性適應任何可被接受的資料型態
預先定義可接受的資料型態
透過不同資料類型的輸入來呼叫所對應的實體
透過不同資料類型的輸入來變更輸入接點
多個實體的組合
單一VI內嵌於Calling VI
需要建立各種實體才能對應其資料型態功能
透過設定跟副檔名即可對應資料型態
可以實現不同程式碼對應不同資料型態的操作
只能透過相同程式碼來對應不同資料型態的操作

這份相關文件可以查詢LabVIEW Help中看到。

當然,Malleable VI也是有缺點的。
首先最大的缺點就是最大的優點:程式碼共用。因此沒辦法根據不同的資料型態來自動切換不同的程式碼。我想這雖是缺點但完全不是問題,因為如果有這種需求,直接使用Polymorphic VI就可以解決了。
另一個缺點就真的等待NI解決了:無法使用在遞迴上。這個超級可惜的啊!如果可以用在遞迴上,基本上各種data parse就可以很簡單的處理掉了。

基本上個人倒是不太常用Malleable VI,其一是因為一開始就把常用的VIM都寫完了,所以後續都只用這些東西。另一方面則是應用的情境仍有侷限,例如相同程式碼能處理的多資料型態的功能有限,大多數都是陣列的操作,如搜尋、排序等,而這些功能也多半被LabVIEW 2017新增的Array function所包含了。



簡單的介紹到這邊,繼續回到跟死線的奮鬥Q_Q